Mercurial > hg-old > index.cgi
view lwdisasm/insn.c @ 417:f792faf877bb
Fixed minor layout glitch in listing code
author | lost@l-w.ca |
---|---|
date | Tue, 10 Aug 2010 23:08:07 -0600 |
parents | cba03436c720 |
children |
line wrap: on
line source
/* insn.c Copyright © 2010 William Astle This file is part of LWTOOLS. LWTOOLS is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <lw_alloc.h> #include <lw_string.h> #include "lwdisasm.h" /* this function creates a linedata_t with the disassembly of the current location; returns NULL if the current disassembly point is not a valid instruction or we are at the end of the input */ #define fb(d) do { int ____t; ____t = fetch_byte(as); if (____t < 0) return NULL; bytes[len++] = ____t; (d) = ____t; } while (0) #define fb2(d) do { int ____t; ____t = fetch_byte(as); if (____t < 0) return "?"; bytes[(*len)++] = ____t; (d) = ____t; } while (0) char *encode_target(disasmstate_t *as, int addr, int section) { symbol_t *s; static char buffer[256]; s = find_symbol(as, addr, section); if (!s) { sprintf(buffer, "$%04X", addr); return buffer; } else { return s -> symbol; } } char *decode_indexed(disasmstate_t *as, char *bytes, int *len, int *target, int section) { int pb, b1, b2; int rn; static char *rs[] = { "x", "y", "u", "s", "pcr" }; static char str[40]; char *i1 = "", *i2 = ""; char *tstr; *target = -1; fb2(pb); rn = (pb >> 5) & 3; if (pb < 0x80) { // 5 bit b1 = pb & 15; if (pb & 16) b1 = b1 - 16; sprintf(str, "%d,%s", b1, rs[rn]); return str; } if ((pb & 0x1F) == 0x1F) { // extended indirect fb2(b1); fb2(b2); sprintf(str, "[$%04X]", (b1 << 8) | b2); return str; } if (pb & 0x10) { i1 = "["; i2 = "]"; } switch (pb & 0x0F) { case 0: // ,r+ if (*i1 == '[') { break; } sprintf(str, "%s,%s+%s", i1, rs[rn], i2); return str; case 1: // ,r++ sprintf(str, "%s,%s++%s", i1, rs[rn], i2); return str; case 2: // ,-r if (*i1 == '[') { break; } sprintf(str, "%s,-%s%s", i1, rs[rn], i2); return str; case 3: // ,--r sprintf(str, "%s,--%s%s", i1, rs[rn], i2); return str; case 4: // ,r sprintf(str, "%s,%s%s", i1, rs[rn], i2); return str; case 5: // B,r sprintf(str, "%sb,%s%s", i1, rs[rn], i2); return str; case 6: // A,r sprintf(str, "%sa,%s%s", i1, rs[rn], i2); return str; case 8: // 8 bit,r fb2(b1); if (b1 > 128) b1 -= 256; sprintf(str, "%s<$%02X,%s%s", i1, b1, rs[rn], i2); return str; case 9: // 16 bit,r fb2(b1); fb2(b2); b1 = (b1 << 8) | b2; if (b2 > 32768) b2 -= 65536; sprintf(str, "%s>$%04X,%s%s", i1, b1, rs[rn], i2); return str; case 11: // D,r sprintf(str, "%sd,%s%s", i1, rs[rn], i2); return str; case 12: // 8 bit,PCR fb2(b1); if (b1 > 127) b1 -= 256; b1 += as -> curoff; b1 &= 0xFFFF; sprintf(str, "%s<%s,pcr%s", i1, encode_target(as, b1, section), i2); *target = b1; return str; case 13: // 16 bit,PCR fb2(b1); fb2(b2); b1 = (b1 << 8) | b2; b1 += as -> curoff; b1 &= 0xFFFF; sprintf(str, "%s>%s,pcr%s", i1, encode_target(as, b1, section), i2); *target = b1; return str; } // if we got here, we have an illegal 6809 if (as -> target == TARGET_6809) { sprintf(str, "?"); return str; } // now sort out 6309 operations pb &= 0x1F; switch (pb) { case 0x07: case 0x17: // E,r sprintf(str, "%se,%s%s", i1, rs[rn], i2); return str; case 0x0A: case 0x1A: // F,r sprintf(str, "%sf,%s%s", i1, rs[rn], i2); return str; case 0x0E: case 0x1E: // W,r sprintf(str, "%sw,%s%s", i1, rs[rn], i2); return str; case 0x0F: case 0x10: // W indexing switch (rn) { case 0: // ,W sprintf(str, "%s,w%s", i1, i2); return str; case 1: // 16 bit,W fb2(b1); fb2(b2); b1 = (b1 << 8) | b2; if (b1 > 32768) b1 -= 65536; sprintf(str, "%s>$%04X,w%s", i1, b1, i2); return str; case 2: // ,W++ sprintf(str, "%s,w++%s", i1, i2); return str; case 3: // ,--W sprintf(str, "%s,--w%s", i1, i2); return str; } } sprintf(str, "?"); return str; } char *decode_operand(disasmstate_t *as, int addrmode, uint8_t *bytes, int *len, int *target, int section) { int b1, b2, b3, b4; static char insnbuffer[256]; char *t; static char *rlist3[] = { "D", "X", "Y", "U", "S", "PC", "W", "V", "A", "B", "CC", "DP", "0", "0", "E", "F" }; static char *rlist8[] = { "D", "X", "Y", "U", "S", "PC", "?", "?", "A", "B", "CC", "DP", "?", "?", "?", "?" }; char **rlist = (as -> target == TARGET_6809) ? rlist8 : rlist3; switch (addrmode) { case ADDR_IMM8: fb2(b1); sprintf(insnbuffer, "#$%02X", b1); break; case ADDR_IMM16: fb2(b1); fb2(b2); sprintf(insnbuffer, "#$%04X", (b1 << 8) | b2); break; case ADDR_IMM32: fb2(b1); fb2(b2); fb2(b3); fb2(b4); sprintf(insnbuffer, "#$%08X", (b1 << 24) | (b2 << 16) | (b3 << 8) | b4); break; case ADDR_DIR: fb2(b1); sprintf(insnbuffer, "<%s", encode_target(as, (as -> dpval << 8) | b1, section)); *target = as -> dpval * 256 + b1; break; case ADDR_EXT: fb2(b1); fb2(b2); sprintf(insnbuffer, ">%s", encode_target(as, (b1 << 8) | b2, section)); *target = (b1 << 8) | b2; break; case ADDR_INH: *insnbuffer = 0; break; case ADDR_IMM8DIR: fb2(b1); fb2(b2); sprintf(insnbuffer, "#$%02X;<%s", b1, encode_target(as, (as -> dpval << 8) | b2, section)); *target = (as -> dpval << 8) | b2; break; case ADDR_IMM8EXT: fb2(b1); fb2(b2); fb2(b3); sprintf(insnbuffer, "#$%02X;>%s", b1, encode_target(as, (b2 << 8) | b3, section)); *target = (b2 << 8) | b3; break; case ADDR_IMM8IND: fb2(b1); t = decode_indexed(as, bytes, len, target, section); sprintf(insnbuffer, "#$%02X;%s", b1, t); break; case ADDR_IND: t = decode_indexed(as, bytes, len, target, section); sprintf(insnbuffer, "%s", t); break; case ADDR_RTOR: fb2(b1); b2 = b1 & 0x0F; b1 = b1 >> 4; sprintf(insnbuffer, "%s,%s", rlist[b1], rlist[b2]); break; case ADDR_BITBIT: fb2(b1); fb2(b2); sprintf(insnbuffer, "%s,%d,%d;<%s", (b1 >> 6 == 0) ? "CC" : ((b1 >> 6 == 1) ? "A" : ((b1 >> 6 == 2) ? "B" : "?")), (b1 >> 3) & 7, b1 & 7, encode_target(as, (as -> dpval << 8) | b2, section)); *target = (as -> dpval << 8) | b2; break; case ADDR_PSHPULS: insnbuffer[0] = 0; fb2(b1); if (b1 & 0x01) { strcat(insnbuffer, ",cc"); } if (b1 & 0x02) { strcat(insnbuffer, ",a"); } if (b1 & 0x04) { strcat(insnbuffer, ",b"); } if (b1 & 0x08) { strcat(insnbuffer, ",dp"); } if (b1 & 0x10) { strcat(insnbuffer, "x"); } if (b1 & 0x20) { strcat(insnbuffer, "y"); } if (b1 & 0x40) { strcat(insnbuffer, "u"); } if (b1 & 0x80) { strcat(insnbuffer, "pc"); } return insnbuffer + 1; break; case ADDR_PSHPULU: insnbuffer[0] = 0; fb2(b1); if (b1 & 0x01) { strcat(insnbuffer, ",cc"); } if (b1 & 0x02) { strcat(insnbuffer, ",a"); } if (b1 & 0x04) { strcat(insnbuffer, ",b"); } if (b1 & 0x08) { strcat(insnbuffer, ",dp"); } if (b1 & 0x10) { strcat(insnbuffer, "x"); } if (b1 & 0x20) { strcat(insnbuffer, "y"); } if (b1 & 0x40) { strcat(insnbuffer, "s"); } if (b1 & 0x80) { strcat(insnbuffer, "pc"); } return insnbuffer + 1; case ADDR_REL8: fb2(b1); if (b1 > 127) b1 -= 256; b1 += as -> curoff; b1 &= 0xFFFF; sprintf(insnbuffer, "%s", encode_target(as, b1, section)); *target = b1; break; case ADDR_REL16: fb2(b1); if (b1 > 32767) b1 -= 65536; b1 += as -> curoff; b1 &= 0xFFFF; sprintf(insnbuffer, "%s", encode_target(as, b1, section)); *target = b2; break; case ADDR_TFMPP: fb2(b1); b2 = b1 & 0x0F; b1 >>= 4; sprintf(insnbuffer, "%s+,%s+", rlist[b1], rlist[b2]); break; case ADDR_TFMMM: fb2(b1); b2 = b1 & 0x0F; b1 >>= 4; sprintf(insnbuffer, "%s-,%s-", rlist[b1], rlist[b2]); break; case ADDR_TFMPC: fb2(b1); b2 = b1 & 0x0F; b1 >>= 4; sprintf(insnbuffer, "%s+,%s", rlist[b1], rlist[b2]); break; case ADDR_TFMCP: fb2(b1); b2 = b1 & 0x0F; b1 >>= 4; sprintf(insnbuffer, "%s,%s+", rlist[b1], rlist[b2]); break; default: sprintf(insnbuffer, "????"); break; } return insnbuffer; } linedata_t *disasm_insn(disasmstate_t *as) { int curbyte; int b1; linedata_t *l; char *opcode; int addrmode; char insnbuffer[256]; char *t; int addr; int len = 0; int8_t bytes[10]; int target = -1; addr = as -> curoff; fb(curbyte); if (curbyte < 0) return NULL; opcode = as->page0[curbyte].op; addrmode = as->page0[curbyte].addrmode; if (addrmode == ADDR_PAGE1) { fb(b1); if (b1 < 0) return NULL; opcode = as->page1[b1].op; addrmode = as->page1[b1].addrmode; curbyte = (curbyte << 8) | b1; } else if (addrmode == ADDR_PAGE2) { fb(b1); if (b1 < 0) return NULL; opcode = as->page2[b1].op; addrmode = as->page2[b1].addrmode; curbyte = (curbyte << 8) | b1; } if (opcode == NULL) return NULL; t = decode_operand(as, addrmode, bytes, &len, &target, 0); if (!t) return NULL; // now create the line structure l = lw_alloc(sizeof(linedata_t)); l -> next = NULL; l -> prev = NULL; l -> address = addr; l -> type = type_code; l -> length = len; l -> bytes = lw_alloc(len); memmove(l -> bytes, bytes, len); l -> isref = 0; l -> symbol = NULL; l -> sectionref = 0; sprintf(insnbuffer, "%s %s", opcode, t); l -> disasm = lw_strdup(insnbuffer); l -> target = target; return l; } void redisasm_insn(disasmstate_t *as, linedata_t *l) { char *opcode; int addrmode; int len = 0; char bytes[15]; int target = -1; char *t; char insnbuf[256]; int ta; int ts; // short circuit if no target in this one if (l -> target == -1) return; opcode = as -> page0[l -> bytes[0]].op; addrmode = as -> page0[l -> bytes[0]].addrmode; ta = as -> curoff; as -> curoff = l -> address + 1; if (addrmode == ADDR_PAGE1) { opcode = as -> page1[l -> bytes[1]].op; addrmode = as -> page1[l -> bytes[1]].addrmode; as -> curoff++; } else if (addrmode == ADDR_PAGE2) { opcode = as -> page2[l -> bytes[1]].op; addrmode = as -> page2[l -> bytes[1]].addrmode; as -> curoff++; } t = decode_operand(as, addrmode, bytes, &len, &target, l -> sectionref); // now create the line structure lw_free(l -> disasm); sprintf(insnbuf, "%s %s", opcode, t); l -> disasm = lw_strdup(insnbuf); }