Commit 78af4d11 by Jessica Hawkwell

started preliminary support for interrupts, stacks, and function calls

1 parent c44caf9d
Pipeline #211 passed
in 1 minute 8 seconds
# project-specific stuffs # project-specific stuffs
*.mem *.mem.txt
*.bin *.bin
*.kc *.kc
......
...@@ -13,8 +13,9 @@ import me.felinewith.kcpu.hardware.Kmcu; ...@@ -13,8 +13,9 @@ import me.felinewith.kcpu.hardware.Kmcu;
import me.felinewith.kcpu.interfaces.IDevice; import me.felinewith.kcpu.interfaces.IDevice;
import me.felinewith.kcpu.interfaces.IMemory; import me.felinewith.kcpu.interfaces.IMemory;
import me.felinewith.kcpu.util.BaseDevice; import me.felinewith.kcpu.util.BaseDevice;
import me.felinewith.kcpu.util.HardwareExec; import me.felinewith.kcpu.util.CPUStoppedException;
import me.felinewith.kcpu.util.HardwareMemIrq; import me.felinewith.kcpu.util.HardwareMemIrq;
import me.felinewith.kcpu.util.HardwareRecvIrq;
/** /**
* *
...@@ -56,45 +57,66 @@ public class KBoard extends BaseDevice implements IMemory { ...@@ -56,45 +57,66 @@ public class KBoard extends BaseDevice implements IMemory {
System.out.println("CPU up..."); System.out.println("CPU up...");
while (cpu.workCycle() != 0xff) { try {
Thread.yield(); while (true) {
cpu.workCycle();
Thread.yield();
}
} }
catch (CPUStoppedException x) {}
System.err.println("CPU Stopped [zpwr]"); System.err.println("CPU Stopped [zpwr]");
tpe.shutdown(); tpe.shutdown();
System.err.println("Timers stopped");
int a; int a;
for (a = 0; a <= 0xf; a++) { for (a = 0; a <= 0xf; a++) {
if (devices[a] != null) { if (devices[a] != null) {
devices[a].powerOff(); devices[a].powerOff();
System.err.println(String.format("device %x stopped", a));
} }
if (memDevs[a] != null) { if (memDevs[a] != null) {
memDevs[a].powerOff(); memDevs[a].powerOff();
System.err.println(String.format("memdev %x stopped", a));
} }
} }
dumpEverything(); dumpEverything();
} }
@Override public void memIrq(short addr) { @Override public void memIrq(short addr, byte irq) {
short dev = checkDevice(addr); short dev = checkDevice(addr);
short rdev = (short)(0x0f & dev); short rdev = (short)(0x0f & dev);
if ( dev == 0x7f ) { devices[0].memIrq(addr); } StackTraceElement ste = Thread.currentThread().getStackTrace()[1];
String className = ste.getClassName();
int sendIrq = 16;
int a;
for (a = 0; a < 16; a++) {
if (devices[a].getClass().getCanonicalName().equals(className)) {
sendIrq = a;
break;
}
}
if ( dev == 0x7f ) { devices[0].memIrq(addr, (byte)sendIrq); }
else if ( dev <= 0x0f ) { else if ( dev <= 0x0f ) {
short devOff = deviceMaps[rdev].getOffset(); short devOff = deviceMaps[rdev].getOffset();
short devAddr = (short)(addr - devOff); short devAddr = (short)(addr - devOff);
tpe.execute(new HardwareMemIrq(devices[rdev], devAddr)); tpe.execute(new HardwareMemIrq(devices[rdev], devAddr, (byte)sendIrq));
} }
else if ( 0x10 <= dev && dev <= 0x1f ) { else if ( 0x10 <= dev && dev <= 0x1f ) {
short devOff = memDevMaps[rdev].getOffset(); short devOff = memDevMaps[rdev].getOffset();
short devAddr = (short)(addr - devOff); short devAddr = (short)(addr - devOff);
tpe.execute(new HardwareMemIrq(memDevs[rdev], devAddr)); tpe.execute(new HardwareMemIrq(memDevs[rdev], devAddr, (byte)sendIrq));
} }
} }
@Override public void sendIrq(byte irq) { @Override public void sendIrq(byte irq) {
if ( irq >= 16 ) { return; } if ( irq >= 16 ) { return; }
if ( devices[irq] != null ) { tpe.execute(new HardwareExec(devices[irq])); } StackTraceElement ste = Thread.currentThread().getStackTrace()[1];
String className = ste.getClassName();
int sendIrq = 16;
int a;
for (a = 0; a < 16; a++) {
if (devices[a].getClass().getCanonicalName().equals(className)) {
sendIrq = a;
break;
}
}
if ( devices[irq] != null ) { tpe.execute(new HardwareRecvIrq(devices[irq], (byte)sendIrq)); }
} }
@Override public short length() { return (short)memory.length; }; @Override public short length() { return (short)memory.length; };
...@@ -233,9 +255,6 @@ public class KBoard extends BaseDevice implements IMemory { ...@@ -233,9 +255,6 @@ public class KBoard extends BaseDevice implements IMemory {
} }
} }
@Override public void exec() {
}
public void dumpEverything() { public void dumpEverything() {
dumpMemory("system", memory); dumpMemory("system", memory);
int a; int a;
...@@ -256,7 +275,7 @@ public class KBoard extends BaseDevice implements IMemory { ...@@ -256,7 +275,7 @@ public class KBoard extends BaseDevice implements IMemory {
dumpMemory(filename, temp); dumpMemory(filename, temp);
} }
public void dumpMemory(String filename, byte[] mem) { public void dumpMemory(String filename, byte[] mem) {
File f = new File(filename.concat(".mem")); File f = new File(filename.concat(".mem.txt"));
try { System.out.println(String.format("Writing %s", f.getCanonicalPath())); } catch (IOException x) {} try { System.out.println(String.format("Writing %s", f.getCanonicalPath())); } catch (IOException x) {}
try (FileWriter fw = new FileWriter(f)) { try (FileWriter fw = new FileWriter(f)) {
int max = mem.length; int max = mem.length;
......
package me.felinewith.kcpu; package me.felinewith.kcpu;
import java.io.PrintStream; import java.io.PrintStream;
import java.util.Arrays;
import me.felinewith.kcpu.interfaces.IMemory; import me.felinewith.kcpu.interfaces.IMemory;
import me.felinewith.kcpu.opcodes.OpDirector; import me.felinewith.kcpu.opcodes.OpDirector;
import me.felinewith.kcpu.util.BaseDevice; import me.felinewith.kcpu.util.BaseDevice;
import me.felinewith.kcpu.util.CPUStoppedException;
import me.felinewith.kcpu.util.Converter;
import me.felinewith.kcpu.util.helpers.MemHelper; import me.felinewith.kcpu.util.helpers.MemHelper;
import me.felinewith.kcpu.util.helpers.ValueHelper; import me.felinewith.kcpu.util.helpers.ValueHelper;
import me.felinewith.kcpu.util.helpers.ValueType; import me.felinewith.kcpu.util.helpers.ValueType;
...@@ -42,9 +45,20 @@ public class Kcpu extends BaseDevice { ...@@ -42,9 +45,20 @@ public class Kcpu extends BaseDevice {
short[] registers; short[] registers;
private KBoard kboard; private KBoard kboard;
Thread initThread;
public Kcpu(KBoard system) { public Kcpu(KBoard system) {
memory = new byte[0x0800]; /**
* memory ranges:
* 0x0000 - 0x00ff : data stack
* 0x0100 - 0x017f : pc stack (return stack)
* 0x0180 - 0x019f : interrupt vectors
* 0x0120 : data stack pointer
* 0x0122 : pc stack pointer
* 0x0124 ~ unused
* 0x01ff : interrupt (boolean value)
*/
memory = new byte[0x0200];
name = "Kcpu"; name = "Kcpu";
settings = new short[6]; settings = new short[6];
kboard = system; kboard = system;
...@@ -54,30 +68,45 @@ public class Kcpu extends BaseDevice { ...@@ -54,30 +68,45 @@ public class Kcpu extends BaseDevice {
} }
@Override public void init(IMemory system) { @Override public void init(IMemory system) {
initThread = Thread.currentThread();
setOuter(System.err); setOuter(System.err);
} }
@Override public void exec() { workCycle(); } // need to prevent other devices from writing to CPU internals
@Override public void write(short offset, byte data) { }
@Override public byte read(short addr) { @Override public void recvIrq(byte irq) {
if ( (0xffff & addr) > length() ) { return (byte)0xff; } synchronized (initThread) {
return memory[0xffff & addr]; short[] regs = Arrays.copyOf(registers, registers.length);
} short counter = pc;
if (Thread.currentThread().getId() != initThread.getId()) {
initThread.interrupt();
regs = Arrays.copyOf(registers, registers.length);
counter = pc;
}
@Override public void write(short offset, byte data) { } short start = (short)((irq * 2) + 0x0180);
@Override public void copy(short addrSrc, short addrDest, IMemory dest) { } pc = Converter.bytes2short(new byte[]{memory[start], memory[start + 1]});
try {
while (true) { workCycle(); Thread.yield(); }
}
catch (CPUStoppedException x) {}
@Override public void memIrq(short addr) { if (Thread.currentThread().getId() != initThread.getId()) {
if (0 <= addr && addr <= memory.length) { exec(); } registers = Arrays.copyOf(regs, regs.length);
pc = counter;
initThread.notify();
}
}
} }
public int workCycle() { public void workCycle() throws CPUStoppedException {
if (pc >= 0xfff0) { pc = 0; } if (pc >= 0xfff0) { pc = 0; }
short inst = MemHelper.readShort(pc, kboard); short inst = MemHelper.readShort(pc, kboard);
short ref = MemHelper.readShort(pc + 2, kboard); short ref = MemHelper.readShort(pc + 2, kboard);
short[] values = new short[4]; short[] values = new short[]{(short)0, (short)1, (short)2, (short)3};
if ((0xffff & inst) == 0xffff){ if ((0xffff & inst) == 0xff1b){
logln("Break!"); log("");
} }
switch (0x0700 & ref) { switch (0x0700 & ref) {
case 0x0700: case 0x0600: case 0x0500: case 0x0700: case 0x0600: case 0x0500:
...@@ -96,8 +125,20 @@ public class Kcpu extends BaseDevice { ...@@ -96,8 +125,20 @@ public class Kcpu extends BaseDevice {
} }
log("%04x : [%10s] %04x ->", pc, ((od == null)?"nop":od.name()), ref); log("%04x : [%10s] %04x ->", pc, ((od == null)?"nop":od.name()), ref);
log(" %04x %04x %04x %04x ", registers[0], registers[1], registers[2], registers[3]);
log(" %04x %04x %04x %04x\t\t", registers[0], registers[1], registers[2], registers[3]); // bring up the program counter
if (od == null) { pc += 12; return; } // inc if nop
pc += 4;
pc += (((0x0700 & ref) >> 8) * 2);
// this works because the value starts counting at 1
switch(0x0700 & ref) {
case 0x0000: ref += ValueType.R.getValue();
case 0x0100: ref += (ValueType.R.getValue() << 2);
case 0x0200: ref += (ValueType.R.getValue() << 4);
case 0x0300: ref += (ValueType.R.getValue() << 6);
}
if ((0x0700 & ref) >= 0x0100) { log(" %2s.%04x", ValueType.valueOf(ref, 0), values[0]); } if ((0x0700 & ref) >= 0x0100) { log(" %2s.%04x", ValueType.valueOf(ref, 0), values[0]); }
if ((0x0700 & ref) >= 0x0200) { log(" %2s.%04x", ValueType.valueOf(ref, 1), values[1]); } if ((0x0700 & ref) >= 0x0200) { log(" %2s.%04x", ValueType.valueOf(ref, 1), values[1]); }
...@@ -105,72 +146,65 @@ public class Kcpu extends BaseDevice { ...@@ -105,72 +146,65 @@ public class Kcpu extends BaseDevice {
if ((0x0700 & ref) >= 0x0400) { log(" %2s.%04x", ValueType.valueOf(ref, 3), values[3]); } if ((0x0700 & ref) >= 0x0400) { log(" %2s.%04x", ValueType.valueOf(ref, 3), values[3]); }
logln(""); logln("");
if (od == null) { pc += 12; return 0; } // inc if nop
pc += 4;
pc += (((0x0700 & ref) >> 8) * 2);
if ( od.hasHandler() ) { if ( od.hasHandler() ) {
registers = od.call(pc, ref, registers, values, kboard); registers = od.call(pc, ref, registers, values, kboard);
return 0; return;
} }
short data = ValueHelper.readShort(0, ref, registers, values, kboard); short data = ValueHelper.readShort(0, ref, registers, values, kboard);
switch (od) { switch (od) {
// device management // device management
case DEVA: registers[0] = kboard.checkDevice(data); return 0; case DEVA: registers[0] = kboard.checkDevice(data); return;
case DEVD: kboard.detachDevice(data); return 0; case DEVD: kboard.detachDevice(data); return;
case DEVM: case DEVM:
kboard.setDeviceRange(data, ValueHelper.readShort(1, ref, registers, values, kboard)); kboard.setDeviceRange(data, ValueHelper.readShort(1, ref, registers, values, kboard));
return 0; return;
case DEVP: case DEVP:
KMemoryRange kmr = kboard.getDeviceRange(data); KMemoryRange kmr = kboard.getDeviceRange(data);
registers[0] = kmr.getOffset(); registers[0] = kmr.getOffset();
registers[1] = kmr.getLength(); registers[1] = kmr.getLength();
return 0; return;
// interrupts // interrupts
case IRQD: kboard.sendIrq((byte)(0x000f & data)); return 0; case IRQD: kboard.sendIrq((byte)(0x000f & data)); return;
case IRQM: kboard.memIrq(data); return 0; case IRQM: kboard.memIrq(data, (byte)0); return;
// jumps // jumps
case JMP: pc = (short)(pc + (0xffff & data)); return 0; case JMP: case JMPU: pc = (short)(pc + (0xffff & data)); return;
case JMPA: pc = data; return 0; case JMPA: pc = data; return;
case JMPD: pc = (short)(pc - (0xffff & data)); return 0; case JMPD: pc = (short)(pc - (0xffff & data)); return;
case GPC: case GPC:
registers = ValueHelper.writeShort(0, ref, registers, values, kboard, pc); registers[0] = pc;
return 0; return;
case ZPWR: return 0xff; case ZPWR: throw new CPUStoppedException("zpwr");
} }
short data2 = ValueHelper.readShort(1, ref, registers, values, kboard); short data2 = ValueHelper.readShort(1, ref, registers, values, kboard);
short data3 = ValueHelper.readShort(2, ref, registers, values, kboard); short data3 = ValueHelper.readShort(2, ref, registers, values, kboard);
switch (od) { switch (od) {
// conditionals // conditionals
case JE: if (data == data2) { pc += data3; } return 0; case JE: if (data == data2) { pc += data3; } return;
case JAE: if (data == data2) { pc = data3; } return 0; case JAE: if (data == data2) { pc = data3; } return;
case JDE: if (data == data2) { pc -= data3; } return 0; case JDE: if (data == data2) { pc -= data3; } return;
case JG: if (data > data2) { pc += data3; } return 0; case JG: if (data > data2) { pc += data3; } return;
case JAG: if (data > data2) { pc = data3; } return 0; case JAG: if (data > data2) { pc = data3; } return;
case JDG: if (data > data2) { pc -= data3; } return 0; case JDG: if (data > data2) { pc -= data3; } return;
case JL: if (data < data2) { pc += data3; } return 0; case JL: if (data < data2) { pc += data3; } return;
case JAL: if (data < data2) { pc = data3; } return 0; case JAL: if (data < data2) { pc = data3; } return;
case JDL: if (data < data2) { pc -= data3; } return 0; case JDL: if (data < data2) { pc -= data3; } return;
case JGE: if (data >= data2) { pc += data3; } return 0; case JGE: if (data >= data2) { pc += data3; } return;
case JAGE: if (data >= data2) { pc = data3; } return 0; case JAGE: if (data >= data2) { pc = data3; } return;
case JDGE: if (data >= data2) { pc -= data3; } return 0; case JDGE: if (data >= data2) { pc -= data3; } return;
case JLE: if (data <= data2) { pc += data3; } return 0; case JLE: if (data <= data2) { pc += data3; } return;
case JALE: if (data <= data2) { pc = data3; } return 0; case JALE: if (data <= data2) { pc = data3; } return;
case JDLE: if (data <= data2) { pc -= data3; } return 0; case JDLE: if (data <= data2) { pc -= data3; } return;
case VCMP: case VCMP:
registers[0] = 0; registers[0] = 0;
if (data != data2) { registers[0] += 0x0001; } if (data != data2) { registers[0] += 0x0001; }
if (data >= data2) { registers[0] += 0x0002; } if (data >= data2) { registers[0] += 0x0002; }
if (data == data2) { registers[0] += 0x0004; } if (data == data2) { registers[0] += 0x0004; }
if (data <= data2) { registers[0] += 0x0008; } if (data <= data2) { registers[0] += 0x0008; }
return 0;
} }
return 0;
} }
} }
...@@ -30,7 +30,7 @@ public class Kemulator { ...@@ -30,7 +30,7 @@ public class Kemulator {
ArrayList<Option> option = new ArrayList<>(); ArrayList<Option> option = new ArrayList<>();
option.add(Option.builder("b") option.add(Option.builder("b")
.longOpt("bootrom") .longOpt("bootrom")
.argName("bootrom.kc") .argName("bootrom")
.hasArg() .hasArg()
.numberOfArgs(8) .numberOfArgs(8)
.build() .build()
......
package me.felinewith.kcpu.hardware; package me.felinewith.kcpu.hardware;
import me.felinewith.kcpu.hardware.kmcu.KmcuOp;
import java.io.PrintStream; import java.io.PrintStream;
import java.util.Arrays; import java.util.Arrays;
import me.felinewith.kcpu.util.Converter; import me.felinewith.kcpu.hardware.kmcu.KmcuOp;
import me.felinewith.kcpu.util.BaseDevice; import me.felinewith.kcpu.util.BaseDevice;
import me.felinewith.kcpu.util.Converter;
/** /**
* *
...@@ -38,11 +38,6 @@ public class Kmcu extends BaseDevice { ...@@ -38,11 +38,6 @@ public class Kmcu extends BaseDevice {
name = "Kmcp"; name = "Kmcp";
} }
@Override public void exec() {
workInit((short)0);
workInit((short)1);
}
private void workInit(short setting) { private void workInit(short setting) {
byte[] reg; byte[] reg;
if (setting == 0) { reg = Arrays.copyOfRange(memory, 0, 7); } if (setting == 0) { reg = Arrays.copyOfRange(memory, 0, 7); }
...@@ -465,9 +460,15 @@ public class Kmcu extends BaseDevice { ...@@ -465,9 +460,15 @@ public class Kmcu extends BaseDevice {
return output; return output;
} }
@Override public void memIrq(short addr) { @Override public void memIrq(short addr, byte irq) {
if ( 0 <= addr && addr <= memory.length ) { exec(); } if ( 0 <= addr && addr <= memory.length ) {
workInit((short)0);
workInit((short)1);
}
} }
@Override public void sendIrq(byte irq) { } @Override public void recvIrq(byte irq) {
workInit((short)0);
workInit((short)1);
}
} }
...@@ -8,5 +8,5 @@ public interface IDevice extends IMemory { ...@@ -8,5 +8,5 @@ public interface IDevice extends IMemory {
public void init(IMemory board); public void init(IMemory board);
public abstract void sendIrq(byte irq); public abstract void sendIrq(byte irq);
public void exec(); public abstract void recvIrq(byte irq);
} }
...@@ -8,8 +8,7 @@ public interface IMemory { ...@@ -8,8 +8,7 @@ public interface IMemory {
public abstract short length(); public abstract short length();
public abstract byte read(short addr); public abstract byte read(short addr);
public abstract void write(short addr, byte data); public abstract void write(short addr, byte data);
public void copy(short addrSrc, short addrDest, IMemory dest); public abstract void memIrq(short addr, byte irq);
public abstract void memIrq(short addr);
public void powerOff(); public void powerOff();
} }
...@@ -6,6 +6,7 @@ import java.io.FileNotFoundException; ...@@ -6,6 +6,7 @@ import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import me.felinewith.kcpu.Kasm; import me.felinewith.kcpu.Kasm;
import me.felinewith.kcpu.Kasm.KasmBuilder;
import me.felinewith.kcpu.util.BaseMemory; import me.felinewith.kcpu.util.BaseMemory;
/** /**
...@@ -15,42 +16,42 @@ import me.felinewith.kcpu.util.BaseMemory; ...@@ -15,42 +16,42 @@ import me.felinewith.kcpu.util.BaseMemory;
public class BootRom extends BaseMemory { public class BootRom extends BaseMemory {
private short writepos; private short writepos;
private short prev;
private short prev2;
private boolean writable; private boolean writable;
public BootRom() { public BootRom() {
writepos = 0; writepos = 0;
prev = 0; writable = true;
prev2 = 0;
writable = false;
memory = new byte[0x1000]; memory = new byte[0x1000];
Arrays.fill(memory, (byte)0xff); Arrays.fill(memory, (byte)0xff);
KasmBuilder kb = Kasm.builder();
kb.setBASEaddr((short)0x1000);
kb.setVerbose(false);
Kasm kasm = kb.build();
// hardcoding some bootrom // hardcoding some bootrom
writeBytes(Kasm.compile("movs $0 r2")); //writeBytes(kasm.compileSegment("movs $0 r2"));
writeBytes(Kasm.compile("add r0 16")); kasm.compileSegment("mark");
writeBytes(Kasm.compile("add r2 1")); writeBytes(kasm.compileSegment("add r0 16"));
writeBytes(Kasm.compile("movs $0 r2")); writeBytes(kasm.compileSegment("add r2 1"));
writeBytes(Kasm.compile("jdl r0 512 22,16")); writeBytes(kasm.compileSegment("movs $0 r2"));
writeBytes(kasm.compileSegment("jdl r0 512 mark"));
//writeBytes(Kasm.compile("movs r0 0")); //writeBytes(Kasm.compile("movs r0 0"));
//writeBytes(Kasm.compile("movs r1 0")); //writeBytes(Kasm.compile("movs r1 0"));
//writeBytes(Kasm.compile("movs r2 0")); //writeBytes(Kasm.compile("movs r2 0"));
//writeBytes(Kasm.compile("movs r3 0")); //writeBytes(Kasm.compile("movs r3 0"));
writeBytes(Kasm.compile("gpc %0300,16")); writeBytes(kasm.compileSegment("gpc"));
writeBytes(Kasm.compile("mov ff00,16 61,16")); writeBytes(kasm.compileSegment("mov ff00,16 61,16"));
writeBytes(Kasm.compile("irqm ff01,16")); writeBytes(kasm.compileSegment("irqm ff01,16"));
} }
@Override public void memIrq(short addr) { // writable at the start, so smart ROMs can rewrite themselves to rearrange stuff
writable = ((prev2 == 0x4b63) && (prev == 0x7075) && (addr == 0x7f)); // useful for moving devices around the address space at boot-time
// then a simple program can write a device table into ROM space
if ((0xff & prev) == 0) { prev += addr; } // finally, send an interrupt to the ROM device to lock it
else if ((0xff00 & prev) == 0) { prev = (short)(prev << 8); prev += addr; } @Override public void memIrq(short addr, byte irq) { writable = false; }
else { prev2 = prev; }
}
@Override public void write(short addr, byte data) { @Override public void write(short addr, byte data) {
if (!writable) { return; } if (!writable) { return; }
......
...@@ -40,7 +40,7 @@ public class Buffer extends BaseMemory { ...@@ -40,7 +40,7 @@ public class Buffer extends BaseMemory {
bufout = new OutputStreamWriter(stdout); bufout = new OutputStreamWriter(stdout);
} }
@Override public void memIrq(short addr) { @Override public void memIrq(short addr, byte irq) {
short a; short a;
short value; short value;
if (addr <= 0x0f) { if (addr <= 0x0f) {
......
package me.felinewith.kcpu.opcodes; package me.felinewith.kcpu.opcodes;
import me.felinewith.kcpu.util.helpers.ValueHelper;
import java.util.Arrays; import java.util.Arrays;
import me.felinewith.kcpu.interfaces.IMemory; import me.felinewith.kcpu.interfaces.IMemory;
import me.felinewith.kcpu.util.helpers.ValueHelper;
/** /**
* *
...@@ -11,8 +11,9 @@ import me.felinewith.kcpu.interfaces.IMemory; ...@@ -11,8 +11,9 @@ import me.felinewith.kcpu.interfaces.IMemory;
public class Memory implements IOpcodeHandler { public class Memory implements IOpcodeHandler {
@Override public short[] opcode(OpDirector opcode, short pc, short ref, short[] regs, short[] values, IMemory memory) { @Override public short[] opcode(OpDirector opcode, short pc, short ref, short[] regs, short[] values, IMemory memory) {
short data;
short[] output = Arrays.copyOf(regs, regs.length); short[] output = Arrays.copyOf(regs, regs.length);
short addr = ValueHelper.readShort(0, ref, output, values, memory);
short data;
switch (opcode) { switch (opcode) {
case MOV: case MOVB: case MOV: case MOVB:
data = ValueHelper.readByte(1, ref, output, values, memory); data = ValueHelper.readByte(1, ref, output, values, memory);
......
...@@ -18,43 +18,59 @@ public enum OpDirector { ...@@ -18,43 +18,59 @@ public enum OpDirector {
MOV (0x0010, Memory.class, "Alias for MOVB"), MOVB(0x0010, Memory.class, "dest value"), MOV (0x0010, Memory.class, "Alias for MOVB"), MOVB(0x0010, Memory.class, "dest value"),
MOVS(0x0011, Memory.class, "dest value"), MOVS(0x0011, Memory.class, "dest value"),
// stack manipulation
PUSH(0x1000, "value: push value to stack"),
POP (0x1001, "pop value off stack"),
CALL(0x1002, "addr: call function at address"),
RET (0x1003, "return from function"),
IRET(0x10f0, "return from interrupt state (does nothing in normal mode)"),
// interrupt vector management
IVEC(0x10f1, "irq addr: set function address for interrupt irq"),
// cpu stuffies // cpu stuffies
DEVA(0xff00, "n0; get device at address n0"), // get device port from address DEVA(0xff00, "addr; get device at address"), // get device port from address
DEVD(0xff01, "n0: detach device on port n0"), // detach device DEVD(0xff01, "port: detach device on port"), // detach device
DEVM(0xff02, "n0 n1: relocate device n0 to address n1"), // relocate device DEVM(0xff02, "port newaddr: relocate device to address"), // relocate device
DEVP(0x1003, "n0: get device address for device on port n0"), // get device address from port DEVP(0x1003, "port: get device address for device on port"), // get device address from port
IRQD(0xff10, "n0: send interrupt to port n0"), // interrupt to port // interrupts
IRQM(0xff11, "n0: send interrupt to memory address n0"), // interrupt to memory IRQD(0xff10, "port: send interrupt to port"), // interrupt to port
IRQM(0xff11, "addr: send interrupt to memory address"), // interrupt to memory
// jumps
JMP (0xff18, "Alias of JMPU"), // jump up JMP (0xff18, "Alias of JMPU"), // jump up
JMPU(0xff18, "n0: jump up n0 addresses"), JMPU(0xff18, "addr: jump up n0 addresses"),
JMPA(0xff19, "n0: jump to address n0"), // jump absolute addr JMPA(0xff19, "addr: jump to address n0"), // jump absolute addr
JMPD(0xff1a, "n0: jump down n0 addresses"), // jump down JMPD(0xff1a, "addr: jump down n0 addresses"), // jump down
GPC (0xff1b, "write instruction pointer"), // get instruction pointer GPC (0xff1b, "write instruction pointer"), // get instruction pointer
// comparisson jumps
JE (0xff20, "Alias of JUE"), // jump if = JE (0xff20, "Alias of JUE"), // jump if =
JUE (0xff20, "n0 n1 n2: jump if n0 == n1, see JMPU"), JUE (0xff20, "n0 n1 addr: jump if n0 == n1, see JMPU"),
JAE (0xff21, "n0 n1 n2: jump if n0 == n1, see JMPA"), JAE (0xff21, "n0 n1 addr: jump if n0 == n1, see JMPA"),
JDE (0xff22, "n0 n1 n2: jump if n0 == n1, see JMPD"), JDE (0xff22, "n0 n1 addr: jump if n0 == n1, see JMPD"),
JG (0xff23, "Alias of JUG"), // jump if > JG (0xff23, "Alias of JUG"), // jump if >
JUG (0xff23, "n0 n1 n2: jump if n0 > n1, see JMPU"), JUG (0xff23, "n0 n1 addr: jump if n0 > n1, see JMPU"),
JAG (0xff24, "n0 n1 n2: jump if n0 > n1, see JMPA"), JAG (0xff24, "n0 n1 addr: jump if n0 > n1, see JMPA"),
JDG (0xff25, "n0 n1 n2: jump if n0 > n1, see JMPD"), JDG (0xff25, "n0 n1 addr: jump if n0 > n1, see JMPD"),
JL (0xff26, "Alias of JUL"), // jump if < JL (0xff26, "Alias of JUL"), // jump if <
JUL (0xff26, "n0 n1 n2: jump if n0 < n1, see JMPU"), JUL (0xff26, "n0 n1 addr: jump if n0 < n1, see JMPU"),
JAL (0xff27, "n0 n1 n2: jump if n0 < n1, see JMPA"), JAL (0xff27, "n0 n1 addr: jump if n0 < n1, see JMPA"),
JDL (0xff28, "n0 n1 n2: jump if n0 < n1, see JMPD"), JDL (0xff28, "n0 n1 addr: jump if n0 < n1, see JMPD"),
JGE (0xff29, "Alias of JUGE"), // jump if >= JGE (0xff29, "Alias of JUGE"), // jump if >=
JUGE(0xff29, "n0 n1 n2: jump if n0 >= n1, see JMPU"), JUGE(0xff29, "n0 n1 addr: jump if n0 >= n1, see JMPU"),
JAGE(0xff2a, "n0 n1 n2: jump if n0 >= n1, see JMPA"), JAGE(0xff2a, "n0 n1 addr: jump if n0 >= n1, see JMPA"),
JDGE(0xff2b, "n0 n1 n2: jump if n0 >= n1, see JMPD"), JDGE(0xff2b, "n0 n1 addr: jump if n0 >= n1, see JMPD"),
JLE (0xff2c, "Alias of JULE"), // jump if <= JLE (0xff2c, "Alias of JULE"), // jump if <=
JULE(0xff2c, "n0 n1 n2: jump if n0 <= n1, see JMPU"), JULE(0xff2c, "n0 n1 addr: jump if n0 <= n1, see JMPU"),
JALE(0xff2d, "n0 n1 n2: jump if n0 <= n1, see JMPA"), JALE(0xff2d, "n0 n1 addr: jump if n0 <= n1, see JMPA"),
JDLE(0xff2e, "n0 n1 n2: jump if n0 <= n1, see JMPD"), JDLE(0xff2e, "n0 n1 addr: jump if n0 <= n1, see JMPD"),
// value compare
VCMP(0xff2f, "n0 n1: performs multiple comparissons of n0 and n1"), VCMP(0xff2f, "n0 n1: performs multiple comparissons of n0 and n1"),
// power
ZPWR(0xffff, "Power off"), // power off ZPWR(0xffff, "Power off"), // power off
; ;
......
...@@ -16,16 +16,13 @@ public abstract class BaseDevice extends BaseMemory implements IDevice { ...@@ -16,16 +16,13 @@ public abstract class BaseDevice extends BaseMemory implements IDevice {
board = system; board = system;
} }
@Override public void memIrq(short addr) {
if ( 0 <= addr && addr <= memory.length ) { exec(); }
}
protected void sendIrq() { protected void sendIrq() {
int addr = memory.length - 1; int addr = memory.length - 1;
sendIrq(memory[addr]); sendIrq(memory[addr]);
} }
@Override public void sendIrq(byte irq) { } @Override public void sendIrq(byte irq) { }
@Override public void recvIrq(byte irq) { }
@Override public short length() { return (short)memory.length; } @Override public short length() { return (short)memory.length; }
......
...@@ -26,13 +26,7 @@ public abstract class BaseMemory implements IMemory { ...@@ -26,13 +26,7 @@ public abstract class BaseMemory implements IMemory {
memory[0xffff & addr] = data; memory[0xffff & addr] = data;
} }
public final void copy(int addrSrc, int addrDest, IMemory dest) { copy((short)addrSrc, (short)addrDest, dest); } @Override public void memIrq(short addr, byte irq) { }
@Override public void copy(short addrSrc, short addrDest, IMemory dest) {
if ( (0xffff & addrSrc) > length() ) { return; }
dest.write(addrDest, read(addrSrc));
}
@Override public void memIrq(short addr) { }
@Override public void powerOff() { } @Override public void powerOff() { }
} }
package me.felinewith.kcpu.util;
/**
*
* @author jlhawkwell
*/
public class CPUStoppedException extends Exception {
/**
* Creates a new instance of <code>CPUStoppedException</code> without detail message.
*/
public CPUStoppedException() {
}
/**
* Constructs an instance of <code>CPUStoppedException</code> with the specified detail message.
*
* @param msg the detail message.
*/
public CPUStoppedException(String msg) {
super(msg);
}
}
package me.felinewith.kcpu.util;
import java.util.TimerTask;
import me.felinewith.kcpu.interfaces.IDevice;
/**
*
* @author jlhawkwell
*/
public class HardwareExec extends TimerTask {
IDevice id;
public HardwareExec(IDevice device) {
id = device;
}
@Override public void run() { id.exec(); }
}
...@@ -11,10 +11,15 @@ public class HardwareMemIrq extends TimerTask { ...@@ -11,10 +11,15 @@ public class HardwareMemIrq extends TimerTask {
IMemory id; IMemory id;
short a; short a;
byte i;
public HardwareMemIrq(IMemory device, short addr) { public HardwareMemIrq(IMemory device, short addr, byte irq) {
id = device; id = device;
a = addr; a = addr;
i = irq;
}
@Override public void run() {
Thread.currentThread().setName(String.format("memIRQ-%02x-%x", id, Thread.currentThread().getId() ));
id.memIrq(a, i);
} }
@Override public void run() { id.memIrq(a); }
} }
...@@ -7,14 +7,17 @@ import me.felinewith.kcpu.interfaces.IDevice; ...@@ -7,14 +7,17 @@ import me.felinewith.kcpu.interfaces.IDevice;
* *
* @author jlhawkwell * @author jlhawkwell
*/ */
public class HardwareSendIrq extends TimerTask { public class HardwareRecvIrq extends TimerTask {
IDevice id; IDevice id;
byte i; byte i;
public HardwareSendIrq(IDevice device, byte irq) { public HardwareRecvIrq(IDevice device, byte irq) {
id = device; id = device;
i = irq; i = irq;
} }
@Override public void run() { id.sendIrq(i); } @Override public void run() {
Thread.currentThread().setName(String.format("recvIRQ-%02x_%02x-%x", id, i, Thread.currentThread().getId() ));
id.recvIrq(i);
}
} }
...@@ -25,6 +25,7 @@ public class ValueHelper { ...@@ -25,6 +25,7 @@ public class ValueHelper {
case 2: cref = (short)(0x0030 & ref); break; case 2: cref = (short)(0x0030 & ref); break;
case 3: cref = (short)(0x00c0 & ref); break; case 3: cref = (short)(0x00c0 & ref); break;
} }
switch (cref) { switch (cref) {
case 0x0000: output = values[pos]; break; case 0x0000: output = values[pos]; break;
case 0x0001: case 0x0004: case 0x0010: case 0x0040: case 0x0001: case 0x0004: case 0x0010: case 0x0040:
...@@ -55,10 +56,14 @@ public class ValueHelper { ...@@ -55,10 +56,14 @@ public class ValueHelper {
case 2: cref = (short)(0x0030 & ref); break; case 2: cref = (short)(0x0030 & ref); break;
case 3: cref = (short)(0x00c0 & ref); break; case 3: cref = (short)(0x00c0 & ref); break;
} }
// short-circuit write to register if position isn't used in the instruction
if (pos > ((0x0f00 & reg) >> 8)) { cref = 1; }
switch (cref) { switch (cref) {
case 0x0000:
case 0x0001: case 0x0004: case 0x0010: case 0x0040: case 0x0001: case 0x0004: case 0x0010: case 0x0040:
output[reg] = data; break; output[reg] = data; break;
case 0x0000:
case 0x0002: case 0x0008: case 0x0020: case 0x0080: case 0x0002: case 0x0008: case 0x0020: case 0x0080:
MemHelper.writeByte(values[pos], data, memory); break; MemHelper.writeByte(values[pos], data, memory); break;
case 0x0003: case 0x000c: case 0x0030: case 0x00c0: case 0x0003: case 0x000c: case 0x0030: case 0x00c0:
...@@ -109,10 +114,16 @@ public class ValueHelper { ...@@ -109,10 +114,16 @@ public class ValueHelper {
case 2: cref = (short)(0x0030 & ref); break; case 2: cref = (short)(0x0030 & ref); break;
case 3: cref = (short)(0x00c0 & ref); break; case 3: cref = (short)(0x00c0 & ref); break;
} }
// short-circuit write to register if position isn't used in the instruction
if (pos > ((0x0f00 & ref) >> 8)) {
cref = 1;
}
switch (cref) { switch (cref) {
case 0x0000:
case 0x0001: case 0x0004: case 0x0010: case 0x0040: case 0x0001: case 0x0004: case 0x0010: case 0x0040:
output[reg] = data; break; output[reg] = data; break;
case 0x0000:
case 0x0002: case 0x0008: case 0x0020: case 0x0080: case 0x0002: case 0x0008: case 0x0020: case 0x0080:
MemHelper.writeShort(values[pos], data, memory); break; MemHelper.writeShort(values[pos], data, memory); break;
case 0x0003: case 0x000c: case 0x0030: case 0x00c0: case 0x0003: case 0x000c: case 0x0030: case 0x00c0:
......
...@@ -10,8 +10,8 @@ public enum ValueType { ...@@ -10,8 +10,8 @@ public enum ValueType {
AD(2), AD(2),
AR(3); AR(3);
int t; short t;
private ValueType(int type) { t = type; } private ValueType(int type) { t = (short)type; }
public static ValueType valueOf(int value, int position) { public static ValueType valueOf(int value, int position) {
int temp = value >> (position * 2); int temp = value >> (position * 2);
...@@ -24,5 +24,5 @@ public enum ValueType { ...@@ -24,5 +24,5 @@ public enum ValueType {
} }
return D; return D;
} }
public int getValue() { return t; } public short getValue() { return t; }
} }
...@@ -2,9 +2,9 @@ movs $0 r2 ...@@ -2,9 +2,9 @@ movs $0 r2
add r0 16 add r0 16
add r2 1 add r2 1
movs $0 r2 movs $0 r2
jdl r0 512 2a,16 jdl r0 512 20,16+a,16
deva 0 deva 0
deva 1 deva 1
gpc gpc
gpc %300,16 gpc %100,16+300,16
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!