Skip to content

Instantly share code, notes, and snippets.

@namuol
Created April 20, 2012 21:26
Show Gist options
  • Save namuol/2431996 to your computer and use it in GitHub Desktop.
Save namuol/2431996 to your computer and use it in GitHub Desktop.
Decompiled source from http://dcpu.com/highnerd -- modified for DCPU emulation benchmarking.
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;
}
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