assembler/disassembler: Fix indirect mem addressing for r15
authorMichael Buesch <mb@bu3sch.de>
Sun, 19 Sep 2010 16:30:59 +0000 (18:30 +0200)
committerMichael Buesch <mb@bu3sch.de>
Sun, 19 Sep 2010 16:30:59 +0000 (18:30 +0200)
Signed-off-by: Michael Buesch <mb@bu3sch.de>
assembler/main.c
assembler/scanner.l
disassembler/main.c

index 6b294a4c46d5ddf825a9924fadbe815d04dea500..c4cad33827a190228e5adc34f8eb86bd0d9cbab1 100644 (file)
@@ -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");
index a9928da083850235afb3a9d300150c66b10d2315..80b204f6df33d3af0398838217c51e8fc29b9e19 100644 (file)
@@ -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; }
index 43415a1d003575c4b92add7de4e7a5d9cb2368f3..869a629f4e636d181ccbbbde7e633ed903f8be32 100644 (file)
@@ -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;
 }