dcpu16

Virtual Machine and Assembler for Notch's DCPU-16 Architecture
git clone http://frotz.net/git/dcpu16.git
Log | Files | Refs | README

emulator.c (4178B)


      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 Implementation */
     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 #include <ctype.h>
     39 
     40 #include "emulator.h"
     41 
     42 extern u16 *disassemble(u16 *pc, char *out);
     43 
     44 static u16 lit[0x20] = {
     45 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     46 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
     47 	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
     48 	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
     49 };
     50 
     51 u16 *dcpu_opr(struct dcpu *d, u16 code) {
     52 	switch (code) {
     53 	case 0x00: case 0x01: case 0x02: case 0x03:
     54 	case 0x04: case 0x05: case 0x06: case 0x07:
     55 		return d->r + code;
     56 	case 0x08: case 0x09: case 0x0a: case 0x0b:
     57 	case 0x0c: case 0x0d: case 0x0e: case 0x0f:
     58 		return d->m + d->r[code & 7];
     59 	case 0x10: case 0x11: case 0x12: case 0x13:
     60 	case 0x14: case 0x15: case 0x16: case 0x17:
     61 		return d->m + ((d->r[code & 7] + d->m[d->pc++]) & 0xffff);
     62 	case 0x18:
     63 		return d->m + d->sp++;
     64 	case 0x19:
     65 		return d->m + d->sp;
     66 	case 0x1a:
     67 		return d->m + (--(d->sp));
     68 	case 0x1b:
     69 		return &d->sp;
     70 	case 0x1c:
     71 		return &d->pc;
     72 	case 0x1d:
     73 		return &d->ov;
     74 	case 0x1e:
     75 		return d->m + d->m[d->pc++];
     76 	case 0x1f:
     77 		return d->m + d->pc++;
     78 	default:
     79 		return lit + (code & 0x1F);
     80 	}
     81 }
     82 
     83 static u8 skiptable[32] = { /* operand forms that advance pc */
     84 	[0x10] = 1, [0x11] = 1, [0x12] = 1, [0x13] = 1,
     85 	[0x14] = 1, [0x15] = 1, [0x16] = 1, [0x17] = 1,
     86 	[0x1E] = 1, [0x1F] = 1,
     87 };
     88 
     89 void dcpu_skip(struct dcpu *d) {
     90 	u16 op = d->m[d->pc++];
     91 	d->pc += skiptable[op >> 10];
     92 	if ((op & 15) == 0)
     93 		d->pc += skiptable[(op >> 4) & 31];	
     94 }
     95 
     96 void dcpu_step(struct dcpu *d) {
     97 	u16 op = d->m[d->pc++];
     98 	u16 dst;
     99 	u32 res;
    100 	u16 a, b, *aa;
    101 
    102 	if ((op & 0xF) == 0) goto extended;
    103 
    104 	aa = dcpu_opr(d, dst = (op >> 4) & 0x3F);
    105 	a = *aa;
    106 	b = *dcpu_opr(d, op >> 10);
    107 
    108 	switch (op & 0xF) {
    109 	case 0x1: res = b; break;
    110 	case 0x2: res = a + b; d->ov = res >> 16; break;	
    111 	case 0x3: res = a - b; d->ov = res >> 16; break;
    112 	case 0x4: res = a * b; d->ov = res >> 16; break;
    113 	case 0x5: if (b) { res = a / b; } else { res = 0; } d->ov = res >> 16; break;
    114 	case 0x6: if (b) { res = a % b; } else { res = 0; } break;
    115 	case 0x7: res = a << b; d->ov = res >> 16; break;
    116 	case 0x8: res = a >> b; d->ov = res >> 16; break;
    117 	case 0x9: res = a & b; break;
    118 	case 0xA: res = a | b; break;
    119 	case 0xB: res = a ^ b; break;
    120 	case 0xC: if (a!=b) dcpu_skip(d); return;
    121 	case 0xD: if (a==b) dcpu_skip(d); return;
    122 	case 0xE: if (a<=b) dcpu_skip(d); return;
    123 	case 0xF: if ((a&b)==0) dcpu_skip(d); return;
    124 	}
    125 
    126 	if (dst < 0x1f) *aa = res;
    127 	return;
    128 
    129 extended:
    130 	a = *dcpu_opr(d, op >> 10);
    131 	switch ((op >> 4) & 0x3F) {
    132 	case 0x01:
    133 		d->m[--(d->sp)] = d->pc;
    134 		d->pc = a;
    135 		return;
    136 	default:
    137 		fprintf(stderr, "< ILLEGAL OPCODE >\n");
    138 		exit(0);
    139 	}
    140 }