Created
April 20, 2012 21:26
-
-
Save namuol/2431996 to your computer and use it in GitHub Desktop.
Decompiled source from http://dcpu.com/highnerd -- modified for DCPU emulation benchmarking.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package computer; | |
import java.io.*; | |
// Referenced classes of package computer: | |
// VirtualMonitor, VirtualKeyboard, AWTKeyMapping | |
public class DCPU { | |
public DCPU() { | |
ram = new char[0x10000]; | |
registers = new char[8]; | |
} | |
public int getAddr(int type) { | |
if (type >= 32) | |
return 0x20000 | type & 0x1f; | |
switch (type & 0xf8) { | |
case 0: // '\0' | |
return 0x10000 + (type & 7); | |
case 8: // '\b' | |
return registers[type & 7]; | |
case 16: // '\020' | |
cycles++; | |
return ram[pc++] + registers[type & 7] & 0xffff; | |
case 24: // '\030' | |
switch (type & 7) { | |
case 0: // '\0' | |
return sp++ & 0xffff; | |
case 1: // '\001' | |
return sp & 0xffff; | |
case 2: // '\002' | |
return --sp & 0xffff; | |
case 3: // '\003' | |
return 0x10008; | |
case 4: // '\004' | |
return 0x10009; | |
case 5: // '\005' | |
return 0x10010; | |
case 6: // '\006' | |
cycles++; | |
return ram[pc++]; | |
} | |
cycles++; | |
return 0x20000 | ram[pc++]; | |
} | |
throw new IllegalStateException((new StringBuilder( | |
"Illegal value type ")).append(type) | |
.append("! How did you manage that!?").toString()); | |
} | |
public char get(int addr) { | |
if (addr < 0x10000) | |
return ram[addr & 0xffff]; | |
if (addr < 0x10008) | |
return registers[addr & 7]; | |
if (addr >= 0x20000) | |
return (char) addr; | |
if (addr == 0x10008) | |
return sp; | |
if (addr == 0x10009) | |
return pc; | |
if (addr == 0x10010) | |
return o; | |
else | |
throw new IllegalStateException((new StringBuilder( | |
"Illegal address ")).append(Integer.toHexString(addr)) | |
.append("! How did you manage that!?").toString()); | |
} | |
public void set(int addr, char val) { | |
if (addr < 0x10000) | |
ram[addr & 0xffff] = val; | |
else if (addr < 0x10008) | |
registers[addr & 7] = val; | |
else if (addr < 0x20000) | |
if (addr == 0x10008) | |
sp = val; | |
else if (addr == 0x10009) | |
pc = val; | |
else if (addr == 0x10010) | |
o = val; | |
else | |
throw new IllegalStateException((new StringBuilder( | |
"Illegal address ")).append(Integer.toHexString(addr)) | |
.append("! How did you manage that!?").toString()); | |
} | |
public static int getInstructionLength(char opcode) { | |
int len = 1; | |
int cmd = opcode & 0xf; | |
if (cmd == 0) { | |
cmd = opcode >> 4 & 0xf; | |
if (cmd > 0) { | |
int atype = opcode >> 10 & 0x3f; | |
if ((atype & 0xf8) == 16 || atype == 31 || atype == 30) | |
len++; | |
} | |
} else { | |
int atype = opcode >> 4 & 0x3f; | |
int btype = opcode >> 10 & 0x3f; | |
if ((atype & 0xf8) == 16 || atype == 31 || atype == 30) | |
len++; | |
if ((btype & 0xf8) == 16 || btype == 31 || btype == 30) | |
len++; | |
} | |
return len; | |
} | |
public void skip() { | |
cycles++; | |
pc += getInstructionLength(ram[pc++]); | |
} | |
public void tick() { | |
cycles++; | |
char opcode = ram[pc++]; | |
int cmd = opcode & 0xf; | |
if (cmd == 0) { | |
cmd = opcode >> 4 & 0xf; | |
if (cmd != 0) { | |
int atype = opcode >> 10 & 0x3f; | |
int aaddr = getAddr(atype); | |
char a = get(aaddr); | |
switch (cmd) { | |
case 1: // '\001' | |
ram[--sp & 0xffff] = (char) ((pc - 2) + getInstructionLength(opcode)); | |
pc = a; | |
break; | |
} | |
} | |
} else { | |
int atype = opcode >> 4 & 0x3f; | |
int btype = opcode >> 10 & 0x3f; | |
int aaddr = getAddr(atype); | |
char a = get(aaddr); | |
int baddr = getAddr(btype); | |
char b = get(baddr); | |
switch (cmd) { | |
default: | |
break; | |
case 1: // '\001' | |
{ | |
a = b; | |
break; | |
} | |
case 2: // '\002' | |
{ | |
cycles++; | |
int val = a + b; | |
a = (char) val; | |
o = (char) (val >> 16); | |
break; | |
} | |
case 3: // '\003' | |
{ | |
cycles++; | |
int val = a - b; | |
a = (char) val; | |
o = (char) (val >> 16); | |
break; | |
} | |
case 4: // '\004' | |
{ | |
cycles++; | |
int val = a * b; | |
a = (char) val; | |
o = (char) (val >> 16); | |
break; | |
} | |
case 5: // '\005' | |
{ | |
cycles += 2; | |
if (b == 0) { | |
a = o = '\0'; | |
} else { | |
long val = ((long) a << 16) / (long) b; | |
a = (char) (int) (val >> 16); | |
o = (char) (int) val; | |
} | |
break; | |
} | |
case 6: // '\006' | |
{ | |
cycles += 2; | |
if (b == 0) | |
a = '\0'; | |
else | |
a %= b; | |
break; | |
} | |
case 7: // '\007' | |
{ | |
cycles++; | |
long val = (long) a << b; | |
a = (char) (int) val; | |
o = (char) (int) (val >> 16); | |
break; | |
} | |
case 8: // '\b' | |
{ | |
cycles++; | |
long val = (long) a << 16 - b; | |
a = (char) (int) (val >> 16); | |
o = (char) (int) val; | |
break; | |
} | |
case 9: // '\t' | |
{ | |
a &= b; | |
break; | |
} | |
case 10: // '\n' | |
{ | |
a |= b; | |
break; | |
} | |
case 11: // '\013' | |
{ | |
a ^= b; | |
break; | |
} | |
case 12: // '\f' | |
{ | |
cycles++; | |
if (a != b) | |
skip(); | |
return; | |
} | |
case 13: // '\r' | |
{ | |
cycles++; | |
if (a == b) | |
skip(); | |
return; | |
} | |
case 14: // '\016' | |
{ | |
cycles++; | |
if (a <= b) | |
skip(); | |
return; | |
} | |
case 15: // '\017' | |
{ | |
cycles++; | |
if ((a & b) == 0) | |
skip(); | |
return; | |
} | |
} | |
set(aaddr, a); | |
} | |
} | |
public static void testCpus(int cpuCount, char ram[]) { | |
DCPU cpus[] = new DCPU[cpuCount]; | |
for (int i = 0; i < cpuCount; i++) { | |
cpus[i] = new DCPU(); | |
for (int j = 0; j < 0x10000; j++) | |
cpus[i].ram[j] = ram[j]; | |
} | |
long ops = 0L; | |
int hz = 0x186a0; | |
int cyclesPerFrame = hz / 60; | |
long nsPerFrame = 0xfe502aL; | |
long nextTime = System.nanoTime(); | |
double tick = 0.0D; | |
double total = 0.0D; | |
long startTime = System.currentTimeMillis(); | |
while (!stop) { | |
long a = System.nanoTime(); | |
while (System.nanoTime() < nextTime) | |
try { | |
Thread.sleep(1L); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
long b = System.nanoTime(); | |
for (int j = 0; j < cpuCount; j++) { | |
while (cpus[j].cycles < cyclesPerFrame) | |
cpus[j].tick(); | |
cpus[j].cycles -= cyclesPerFrame; | |
} | |
long c = System.nanoTime(); | |
ops += cyclesPerFrame; | |
nextTime += nsPerFrame; | |
tick += (double) (c - b) / 1000000000D; | |
total += (double) (c - a) / 1000000000D; | |
while (System.currentTimeMillis() > startTime) { | |
long passedTime = System.currentTimeMillis() - startTime; | |
startTime += 1000L; | |
System.out | |
.println((new StringBuilder(String.valueOf(cpuCount))) | |
.append(" DCPU at ") | |
.append((double) ops / (double) passedTime) | |
.append(" khz, ").append((tick * 100D) / total) | |
.append("% cpu use").toString()); | |
tick = total = ops = 0L; | |
} | |
} | |
} | |
public static void main(String args[]) throws Exception { | |
final DCPU cpu = new DCPU(); | |
DataInputStream dis = new DataInputStream( | |
DCPU.class.getResourceAsStream("mem.dmp")); | |
try { | |
int i = 0; | |
do { | |
char ch = dis.readChar(); | |
cpu.ram[i] = ch; | |
i++; | |
} while (true); | |
} catch (EOFException e) { | |
e.printStackTrace(); | |
} | |
dis.close(); | |
dump(cpu.ram, 0, 768); | |
if (args.length == 0) { | |
testCpus(100, cpu.ram); | |
return; | |
} | |
int threads = args.length <= 0 ? 1 : Integer.parseInt(args[0]); | |
final int cpusPerCore = args.length <= 1 ? 100 : Integer | |
.parseInt(args[1]); | |
int seconds = args.length <= 2 ? 5 : Integer.parseInt(args[2]); | |
System.out.println((new StringBuilder("Aiming at 100 khz, with ")) | |
.append(cpusPerCore).append(" DCPUs per thread, on ") | |
.append(threads).append(" threads.").toString()); | |
System.out.println(""); | |
System.out.println((new StringBuilder("Running test for ")) | |
.append(seconds).append(" seconds..").toString()); | |
for (int i = 0; i < threads; i++) { | |
(new Thread() { | |
public void run() { | |
DCPU.testCpus(cpusPerCore, cpu.ram); | |
} | |
}).start(); | |
} | |
for (int i = seconds; i > 0; i--) { | |
System.out.println((new StringBuilder(String.valueOf(i))).append( | |
"..").toString()); | |
Thread.sleep(1000L); | |
} | |
stop = true; | |
} | |
private static void dump(char ram[], int start, int len) { | |
for (int i = 0; i < len;) { | |
String str; | |
for (str = Integer.toHexString(i); str.length() < 4; str = (new StringBuilder( | |
"0")).append(str).toString()) | |
; | |
System.out.print((new StringBuilder(String.valueOf(str))).append( | |
":").toString()); | |
for (int j = 0; j < 8 && i < len; i++) { | |
for (str = Integer.toHexString(ram[i]); str.length() < 4; str = (new StringBuilder( | |
"0")).append(str).toString()) | |
; | |
System.out.print((new StringBuilder(" ")).append(str) | |
.toString()); | |
j++; | |
} | |
System.out.println(); | |
} | |
} | |
public char ram[]; | |
public char pc; | |
public char sp; | |
public char o; | |
public char registers[]; | |
public int cycles; | |
public static volatile boolean stop = false; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package computer; | |
import java.applet.Applet; | |
import java.io.*; | |
// Referenced classes of package computer: | |
// DCPU, VirtualMonitor, VirtualKeyboard, AWTKeyMapping | |
public class DCPUApplet extends Applet | |
implements Runnable | |
{ | |
public DCPUApplet() | |
{ | |
} | |
public void start() | |
{ | |
(new Thread(this)).start(); | |
} | |
public void stop() | |
{ | |
DCPU.stop = true; | |
} | |
public void run() | |
{ | |
try | |
{ | |
DCPU cpu = new DCPU(); | |
DataInputStream dis = new DataInputStream(DCPU.class.getResourceAsStream("mem.dmp")); | |
try | |
{ | |
int i = 0; | |
do | |
{ | |
char ch = dis.readChar(); | |
cpu.ram[i] = ch; | |
i++; | |
} while(true); | |
} | |
catch(EOFException eofexception) | |
{ | |
dis.close(); | |
} | |
DCPU.testCpus(100, cpu.ram); | |
} | |
catch(Exception e) | |
{ | |
e.printStackTrace(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment