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 }