dcpu16

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 9c994b3b9569b6dca35fcfd9f79da7edc332cc53
parent 40fccc47a931f670158243117e867fc1f9e34528
Author: Brian Swetland <swetland@frotz.net>
Date:   Wed,  4 Apr 2012 22:58:22 -0700

disassmbly support

- utility routine to disassemble one instruction
- emulator disassembles the current instruction in state dump
- assembler includes disassembly in the output

Diffstat:
MMakefile | 8++++----
Ma16.c | 31+++++++++++++++++++++----------
Mdcpu.c | 14++++++++++----
Adisassemble.c | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 124 insertions(+), 18 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,11 +1,11 @@ all: dcpu a16 -dcpu: dcpu.c - gcc -Wall -o dcpu dcpu.c +dcpu: dcpu.c disassemble.c + gcc -Wall -o dcpu dcpu.c disassemble.c -a16: a16.c - gcc -Wall -o a16 a16.c +a16: a16.c disassemble.c + gcc -Wall -o a16 a16.c disassemble.c clean: rm -f dcpu a16 diff --git a/a16.c b/a16.c @@ -41,6 +41,8 @@ typedef uint16_t u16; typedef uint32_t u32; +extern u16 *disassemble(u16 *pc, char *out); + static u16 image[65536] = { 0, }; static u16 PC = 0; static FILE *fin; @@ -151,10 +153,6 @@ static const char *tnames[] = { ",", "[", "]", ":", "+", "<STRING>", "<NUMBER>", "<EOF>", }; -static const char *rnames[] = { - "A", "B", "C", "X", "Y", "Z", "I", "J", -}; - #define LASTKEYWORD tWORD int _next(void) { @@ -329,13 +327,24 @@ done: void emit(const char *fn) { FILE *fp; - int n; + u16 *pc = image; + u16 *end = image + PC; + u16 *dis = pc; filename = fn; linenumber = 0; fp = fopen(fn, "w"); if (!fp) die("cannot write file"); - for (n = 0; n < PC; n++) - fprintf(fp, "%04x\n", image[n]); + + while (pc < end) { + if (pc == dis) { + char out[128]; + dis = disassemble(pc, out); + fprintf(fp, "%04x\t%04x:\t%s\n", *pc, (unsigned)(pc-image), out); + } else { + fprintf(fp, "%04x\n", *pc); + } + pc++; + } fclose(fp); } @@ -359,9 +368,11 @@ int main(int argc, char **argv) { assemble(argv[0]); } - linebuffer[0] = 0; - resolve_fixups(); - emit(outfn); + if (PC != 0) { + linebuffer[0] = 0; + resolve_fixups(); + emit(outfn); + } return 0; } diff --git a/dcpu.c b/dcpu.c @@ -40,6 +40,8 @@ typedef uint16_t u16; typedef uint32_t u32; +extern u16 *disassemble(u16 *pc, char *out); + struct dcpu { u16 r[8]; u16 pc; @@ -151,15 +153,19 @@ void dcpu_step(struct dcpu *d) { void dumpheader(void) { fprintf(stderr, - "PC SP OV SKIP A B C X Y Z I J\n" - "---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----\n"); + "PC SP OV SKIP A B C X Y Z I J Instruction\n" + "---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- -----------\n"); } void dumpstate(struct dcpu *d) { + char out[128]; + disassemble(d->m + d->pc, out); fprintf(stderr, - "%04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n", + "%04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %s\n", d->pc, d->sp, d->ov, d->skip, - d->r[0], d->r[1], d->r[2], d->r[3], d->r[4], d->r[5], d->r[6], d->r[7]); + d->r[0], d->r[1], d->r[2], d->r[3], + d->r[4], d->r[5], d->r[6], d->r[7], + out); } void load(struct dcpu *d, const char *fn) { diff --git a/disassemble.c b/disassemble.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2012, Brian Swetland + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* A DCPU-16 Disassembler */ + +/* DCPU-16 Spec is Copyright 2012 Mojang */ +/* http://0x10c.com/doc/dcpu-16.txt */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + +typedef uint16_t u16; + +static const char *opcode[] = { + "XXX", "SET", "ADD", "SUB", "MUL", "DIV", "MOD", "SHL", + "SHR", "AND", "BOR", "XOR", "IFE", "IFN", "IFG", "IFB", +}; +static const char regs[8] = "ABCXYZIJ"; + +static u16 *dis_operand(u16 *pc, u16 n, char *out) { + if (n < 0x08) { + sprintf(out,"%c",regs[n & 7]); + } else if (n < 0x10) { + sprintf(out,"[%c]",regs[n & 7]); + } else if (n < 0x18) { + sprintf(out,"[0x%04x+%c]",*pc++,regs[n & 7]); + } else if (n > 0x1f) { + sprintf(out,"%d", n - 0x20); + } else switch (n) { + case 0x18: strcpy(out,"POP"); break; + case 0x19: strcpy(out,"PEEK"); break; + case 0x1A: strcpy(out,"PUSH"); break; + case 0x1B: strcpy(out,"SP"); break; + case 0x1C: strcpy(out,"PC"); break; + case 0x1D: strcpy(out,"O"); break; + case 0x1e: sprintf(out,"[0x%04x]",*pc++); break; + case 0x1f: sprintf(out,"0x%04x",*pc++); break; + } + return pc; +} +u16 *disassemble(u16 *pc, char *out) { + u16 n = *pc++; + u16 op = n & 0xF; + u16 a = (n >> 4) & 0x3F; + u16 b = (n >> 10); + if (op > 0) { + sprintf(out,"%s ",opcode[op]); + pc = dis_operand(pc, a, out+strlen(out)); + sprintf(out+strlen(out),", "); + pc = dis_operand(pc, b, out+strlen(out)); + return pc; + } + if (a == 1) { + sprintf(out,"JSR "); + pc = dis_operand(pc, b, out+strlen(out)); + return pc; + } + sprintf(out,"UNK[%02x] ", a); + pc = dis_operand(pc, b, out+strlen(out)); + return pc; +} +