disassemble.c (3070B)
1 /* 2 * Copyright (c) 2012, Brian Swetland 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 */ 28 29 /* A DCPU-16 Disassembler */ 30 31 /* DCPU-16 Spec is Copyright 2012 Mojang */ 32 /* http://0x10c.com/doc/dcpu-16.txt */ 33 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <stdint.h> 37 #include <string.h> 38 39 typedef uint16_t u16; 40 41 static const char *opcode[] = { 42 "XXX", "MOV", "ADD", "SUB", "MUL", "DIV", "MOD", "SHL", 43 "SHR", "AND", "BOR", "XOR", "IFE", "IFN", "IFG", "IFB", 44 }; 45 static const char regs[8] = "ABCXYZIJ"; 46 47 static u16 *dis_operand(u16 *pc, u16 n, char *out) { 48 if (n < 0x08) { 49 sprintf(out,"%c",regs[n & 7]); 50 } else if (n < 0x10) { 51 sprintf(out,"[%c]",regs[n & 7]); 52 } else if (n < 0x18) { 53 sprintf(out,"[%c, 0x%04x]",regs[n & 7], *pc++); 54 } else if (n > 0x1f) { 55 sprintf(out,"%d", n - 0x20); 56 } else switch (n) { 57 case 0x18: strcpy(out,"POP"); break; 58 case 0x19: strcpy(out,"PEEK"); break; 59 case 0x1A: strcpy(out,"PUSH"); break; 60 case 0x1B: strcpy(out,"SP"); break; 61 case 0x1C: strcpy(out,"PC"); break; 62 case 0x1D: strcpy(out,"O"); break; 63 case 0x1e: sprintf(out,"[0x%04x]",*pc++); break; 64 case 0x1f: sprintf(out,"0x%04x",*pc++); break; 65 } 66 return pc; 67 } 68 u16 *disassemble(u16 *pc, char *out) { 69 u16 n = *pc++; 70 u16 op = n & 0xF; 71 u16 a = (n >> 4) & 0x3F; 72 u16 b = (n >> 10); 73 if (op > 0) { 74 if ((n & 0x03FF) == 0x1C1) { 75 sprintf(out,"JMP "); 76 pc = dis_operand(pc, b, out+strlen(out)); 77 return pc; 78 } 79 sprintf(out,"%s ",opcode[op]); 80 pc = dis_operand(pc, a, out+strlen(out)); 81 sprintf(out+strlen(out),", "); 82 pc = dis_operand(pc, b, out+strlen(out)); 83 return pc; 84 } 85 if (a == 1) { 86 sprintf(out,"JSR "); 87 pc = dis_operand(pc, b, out+strlen(out)); 88 return pc; 89 } 90 sprintf(out,"UNK[%02x] ", a); 91 pc = dis_operand(pc, b, out+strlen(out)); 92 return pc; 93 } 94