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
*.mem
*.mem.txt
*.bin
*.kc
......
......@@ -13,8 +13,9 @@ import me.felinewith.kcpu.hardware.Kmcu;
import me.felinewith.kcpu.interfaces.IDevice;
import me.felinewith.kcpu.interfaces.IMemory;
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.HardwareRecvIrq;
/**
*
......@@ -56,45 +57,66 @@ public class KBoard extends BaseDevice implements IMemory {
System.out.println("CPU up...");
while (cpu.workCycle() != 0xff) {
Thread.yield();
try {
while (true) {
cpu.workCycle();
Thread.yield();
}
}
catch (CPUStoppedException x) {}
System.err.println("CPU Stopped [zpwr]");
tpe.shutdown();
System.err.println("Timers stopped");
int a;
for (a = 0; a <= 0xf; a++) {
if (devices[a] != null) {
devices[a].powerOff();
System.err.println(String.format("device %x stopped", a));
}
if (memDevs[a] != null) {
memDevs[a].powerOff();
System.err.println(String.format("memdev %x stopped", a));
}
}
dumpEverything();
}
@Override public void memIrq(short addr) {
@Override public void memIrq(short addr, byte irq) {
short dev = checkDevice(addr);
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 ) {
short devOff = deviceMaps[rdev].getOffset();
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 ) {
short devOff = memDevMaps[rdev].getOffset();
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) {
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; };
......@@ -233,9 +255,6 @@ public class KBoard extends BaseDevice implements IMemory {
}
}
@Override public void exec() {
}
public void dumpEverything() {
dumpMemory("system", memory);
int a;
......@@ -256,7 +275,7 @@ public class KBoard extends BaseDevice implements IMemory {
dumpMemory(filename, temp);
}
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 (FileWriter fw = new FileWriter(f)) {
int max = mem.length;
......
package me.felinewith.kcpu;
import java.io.PrintStream;
import java.util.Arrays;
import me.felinewith.kcpu.interfaces.IMemory;
import me.felinewith.kcpu.opcodes.OpDirector;
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.ValueHelper;
import me.felinewith.kcpu.util.helpers.ValueType;
......@@ -42,9 +45,20 @@ public class Kcpu extends BaseDevice {
short[] registers;
private KBoard kboard;
Thread initThread;
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";
settings = new short[6];
kboard = system;
......@@ -54,30 +68,45 @@ public class Kcpu extends BaseDevice {
}
@Override public void init(IMemory system) {
initThread = Thread.currentThread();
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) {
if ( (0xffff & addr) > length() ) { return (byte)0xff; }
return memory[0xffff & addr];
}
@Override public void recvIrq(byte irq) {
synchronized (initThread) {
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) { }
@Override public void copy(short addrSrc, short addrDest, IMemory dest) { }
short start = (short)((irq * 2) + 0x0180);
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 (0 <= addr && addr <= memory.length) { exec(); }
if (Thread.currentThread().getId() != initThread.getId()) {
registers = Arrays.copyOf(regs, regs.length);
pc = counter;
initThread.notify();
}
}
}
public int workCycle() {
public void workCycle() throws CPUStoppedException {
if (pc >= 0xfff0) { pc = 0; }
short inst = MemHelper.readShort(pc, kboard);
short ref = MemHelper.readShort(pc + 2, kboard);
short[] values = new short[4];
if ((0xffff & inst) == 0xffff){
logln("Break!");
short[] values = new short[]{(short)0, (short)1, (short)2, (short)3};
if ((0xffff & inst) == 0xff1b){
log("");
}
switch (0x0700 & ref) {
case 0x0700: case 0x0600: case 0x0500:
......@@ -96,8 +125,20 @@ public class Kcpu extends BaseDevice {
}
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) >= 0x0200) { log(" %2s.%04x", ValueType.valueOf(ref, 1), values[1]); }
......@@ -105,72 +146,65 @@ public class Kcpu extends BaseDevice {
if ((0x0700 & ref) >= 0x0400) { log(" %2s.%04x", ValueType.valueOf(ref, 3), values[3]); }
logln("");
if (od == null) { pc += 12; return 0; } // inc if nop
pc += 4;
pc += (((0x0700 & ref) >> 8) * 2);
if ( od.hasHandler() ) {
registers = od.call(pc, ref, registers, values, kboard);
return 0;
return;
}
short data = ValueHelper.readShort(0, ref, registers, values, kboard);
switch (od) {
// device management
case DEVA: registers[0] = kboard.checkDevice(data); return 0;
case DEVD: kboard.detachDevice(data); return 0;
case DEVA: registers[0] = kboard.checkDevice(data); return;
case DEVD: kboard.detachDevice(data); return;
case DEVM:
kboard.setDeviceRange(data, ValueHelper.readShort(1, ref, registers, values, kboard));
return 0;
return;
case DEVP:
KMemoryRange kmr = kboard.getDeviceRange(data);
registers[0] = kmr.getOffset();
registers[1] = kmr.getLength();
return 0;
return;
// interrupts
case IRQD: kboard.sendIrq((byte)(0x000f & data)); return 0;
case IRQM: kboard.memIrq(data); return 0;
case IRQD: kboard.sendIrq((byte)(0x000f & data)); return;
case IRQM: kboard.memIrq(data, (byte)0); return;
// jumps
case JMP: pc = (short)(pc + (0xffff & data)); return 0;
case JMPA: pc = data; return 0;
case JMPD: pc = (short)(pc - (0xffff & data)); return 0;
case JMP: case JMPU: pc = (short)(pc + (0xffff & data)); return;
case JMPA: pc = data; return;
case JMPD: pc = (short)(pc - (0xffff & data)); return;
case GPC:
registers = ValueHelper.writeShort(0, ref, registers, values, kboard, pc);
return 0;
case ZPWR: return 0xff;
registers[0] = pc;
return;
case ZPWR: throw new CPUStoppedException("zpwr");
}
short data2 = ValueHelper.readShort(1, ref, registers, values, kboard);
short data3 = ValueHelper.readShort(2, ref, registers, values, kboard);
switch (od) {
// conditionals
case JE: if (data == data2) { pc += data3; } return 0;
case JAE: if (data == data2) { pc = data3; } return 0;
case JDE: if (data == data2) { pc -= data3; } return 0;
case JG: if (data > data2) { pc += data3; } return 0;
case JAG: if (data > data2) { pc = data3; } return 0;
case JDG: if (data > data2) { pc -= data3; } return 0;
case JL: if (data < data2) { pc += data3; } return 0;
case JAL: if (data < data2) { pc = data3; } return 0;
case JDL: if (data < data2) { pc -= data3; } return 0;
case JGE: if (data >= data2) { pc += data3; } return 0;
case JAGE: if (data >= data2) { pc = data3; } return 0;
case JDGE: if (data >= data2) { pc -= data3; } return 0;
case JLE: if (data <= data2) { pc += data3; } return 0;
case JALE: if (data <= data2) { pc = data3; } return 0;
case JDLE: if (data <= data2) { pc -= data3; } return 0;
case JE: if (data == data2) { pc += data3; } return;
case JAE: if (data == data2) { pc = data3; } return;
case JDE: if (data == data2) { pc -= data3; } return;
case JG: if (data > data2) { pc += data3; } return;
case JAG: if (data > data2) { pc = data3; } return;
case JDG: if (data > data2) { pc -= data3; } return;
case JL: if (data < data2) { pc += data3; } return;
case JAL: if (data < data2) { pc = data3; } return;
case JDL: if (data < data2) { pc -= data3; } return;
case JGE: if (data >= data2) { pc += data3; } return;
case JAGE: if (data >= data2) { pc = data3; } return;
case JDGE: if (data >= data2) { pc -= data3; } return;
case JLE: if (data <= data2) { pc += data3; } return;
case JALE: if (data <= data2) { pc = data3; } return;
case JDLE: if (data <= data2) { pc -= data3; } return;
case VCMP:
registers[0] = 0;
if (data != data2) { registers[0] += 0x0001; }
if (data >= data2) { registers[0] += 0x0002; }
if (data == data2) { registers[0] += 0x0004; }
if (data <= data2) { registers[0] += 0x0008; }
return 0;
}
return 0;
}
}
......@@ -30,7 +30,7 @@ public class Kemulator {
ArrayList<Option> option = new ArrayList<>();
option.add(Option.builder("b")
.longOpt("bootrom")
.argName("bootrom.kc")
.argName("bootrom")
.hasArg()
.numberOfArgs(8)
.build()
......
package me.felinewith.kcpu.hardware;
import me.felinewith.kcpu.hardware.kmcu.KmcuOp;
import java.io.PrintStream;
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.Converter;
/**
*
......@@ -38,11 +38,6 @@ public class Kmcu extends BaseDevice {
name = "Kmcp";
}
@Override public void exec() {
workInit((short)0);
workInit((short)1);
}
private void workInit(short setting) {
byte[] reg;
if (setting == 0) { reg = Arrays.copyOfRange(memory, 0, 7); }
......@@ -465,9 +460,15 @@ public class Kmcu extends BaseDevice {
return output;
}
@Override public void memIrq(short addr) {
if ( 0 <= addr && addr <= memory.length ) { exec(); }
@Override public void memIrq(short addr, byte irq) {
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 {
public void init(IMemory board);
public abstract void sendIrq(byte irq);
public void exec();
public abstract void recvIrq(byte irq);
}
......@@ -8,8 +8,7 @@ public interface IMemory {
public abstract short length();
public abstract byte read(short addr);
public abstract void write(short addr, byte data);
public void copy(short addrSrc, short addrDest, IMemory dest);
public abstract void memIrq(short addr);
public abstract void memIrq(short addr, byte irq);
public void powerOff();
}
......@@ -6,6 +6,7 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import me.felinewith.kcpu.Kasm;
import me.felinewith.kcpu.Kasm.KasmBuilder;
import me.felinewith.kcpu.util.BaseMemory;
/**
......@@ -15,42 +16,42 @@ import me.felinewith.kcpu.util.BaseMemory;
public class BootRom extends BaseMemory {
private short writepos;
private short prev;
private short prev2;
private boolean writable;
public BootRom() {
writepos = 0;
prev = 0;
prev2 = 0;
writable = false;
writable = true;
memory = new byte[0x1000];
Arrays.fill(memory, (byte)0xff);
KasmBuilder kb = Kasm.builder();
kb.setBASEaddr((short)0x1000);
kb.setVerbose(false);
Kasm kasm = kb.build();
// hardcoding some bootrom
writeBytes(Kasm.compile("movs $0 r2"));
writeBytes(Kasm.compile("add r0 16"));
writeBytes(Kasm.compile("add r2 1"));
writeBytes(Kasm.compile("movs $0 r2"));
writeBytes(Kasm.compile("jdl r0 512 22,16"));
//writeBytes(kasm.compileSegment("movs $0 r2"));
kasm.compileSegment("mark");
writeBytes(kasm.compileSegment("add r0 16"));
writeBytes(kasm.compileSegment("add r2 1"));
writeBytes(kasm.compileSegment("movs $0 r2"));
writeBytes(kasm.compileSegment("jdl r0 512 mark"));
//writeBytes(Kasm.compile("movs r0 0"));
//writeBytes(Kasm.compile("movs r1 0"));
//writeBytes(Kasm.compile("movs r2 0"));
//writeBytes(Kasm.compile("movs r3 0"));
writeBytes(Kasm.compile("gpc %0300,16"));
writeBytes(Kasm.compile("mov ff00,16 61,16"));
writeBytes(Kasm.compile("irqm ff01,16"));
writeBytes(kasm.compileSegment("gpc"));
writeBytes(kasm.compileSegment("mov ff00,16 61,16"));
writeBytes(kasm.compileSegment("irqm ff01,16"));
}
@Override public void memIrq(short addr) {
writable = ((prev2 == 0x4b63) && (prev == 0x7075) && (addr == 0x7f));
if ((0xff & prev) == 0) { prev += addr; }
else if ((0xff00 & prev) == 0) { prev = (short)(prev << 8); prev += addr; }
else { prev2 = prev; }
}
// writable at the start, so smart ROMs can rewrite themselves to rearrange stuff
// useful for moving devices around the address space at boot-time
// then a simple program can write a device table into ROM space
// finally, send an interrupt to the ROM device to lock it
@Override public void memIrq(short addr, byte irq) { writable = false; }
@Override public void write(short addr, byte data) {
if (!writable) { return; }
......
......@@ -40,7 +40,7 @@ public class Buffer extends BaseMemory {
bufout = new OutputStreamWriter(stdout);
}
@Override public void memIrq(short addr) {
@Override public void memIrq(short addr, byte irq) {
short a;
short value;
if (addr <= 0x0f) {
......
package me.felinewith.kcpu.opcodes;
import me.felinewith.kcpu.util.helpers.ValueHelper;
import java.util.Arrays;
import me.felinewith.kcpu.interfaces.IMemory;
import me.felinewith.kcpu.util.helpers.ValueHelper;
/**
*
......@@ -11,8 +11,9 @@ import me.felinewith.kcpu.interfaces.IMemory;
public class Memory implements IOpcodeHandler {
@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 addr = ValueHelper.readShort(0, ref, output, values, memory);
short data;
switch (opcode) {
case MOV: case MOVB:
data = ValueHelper.readByte(1, ref, output, values, memory);
......
......@@ -18,43 +18,59 @@ public enum OpDirector {
MOV (0x0010, Memory.class, "Alias for MOVB"), MOVB(0x0010, 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
DEVA(0xff00, "n0; get device at address n0"), // get device port from address
DEVD(0xff01, "n0: detach device on port n0"), // detach device
DEVM(0xff02, "n0 n1: relocate device n0 to address n1"), // relocate device
DEVP(0x1003, "n0: get device address for device on port n0"), // get device address from port
DEVA(0xff00, "addr; get device at address"), // get device port from address
DEVD(0xff01, "port: detach device on port"), // detach device
DEVM(0xff02, "port newaddr: relocate device to address"), // relocate device
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
IRQM(0xff11, "n0: send interrupt to memory address n0"), // interrupt to memory
// interrupts
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
JMPU(0xff18, "n0: jump up n0 addresses"),
JMPA(0xff19, "n0: jump to address n0"), // jump absolute addr
JMPD(0xff1a, "n0: jump down n0 addresses"), // jump down
JMPU(0xff18, "addr: jump up n0 addresses"),
JMPA(0xff19, "addr: jump to address n0"), // jump absolute addr
JMPD(0xff1a, "addr: jump down n0 addresses"), // jump down
GPC (0xff1b, "write instruction pointer"), // get instruction pointer
// comparisson jumps
JE (0xff20, "Alias of JUE"), // jump if =
JUE (0xff20, "n0 n1 n2: jump if n0 == n1, see JMPU"),
JAE (0xff21, "n0 n1 n2: jump if n0 == n1, see JMPA"),
JDE (0xff22, "n0 n1 n2: jump if n0 == n1, see JMPD"),
JUE (0xff20, "n0 n1 addr: jump if n0 == n1, see JMPU"),
JAE (0xff21, "n0 n1 addr: jump if n0 == n1, see JMPA"),
JDE (0xff22, "n0 n1 addr: jump if n0 == n1, see JMPD"),
JG (0xff23, "Alias of JUG"), // jump if >
JUG (0xff23, "n0 n1 n2: jump if n0 > n1, see JMPU"),
JAG (0xff24, "n0 n1 n2: jump if n0 > n1, see JMPA"),
JDG (0xff25, "n0 n1 n2: jump if n0 > n1, see JMPD"),
JUG (0xff23, "n0 n1 addr: jump if n0 > n1, see JMPU"),
JAG (0xff24, "n0 n1 addr: jump if n0 > n1, see JMPA"),
JDG (0xff25, "n0 n1 addr: jump if n0 > n1, see JMPD"),
JL (0xff26, "Alias of JUL"), // jump if <
JUL (0xff26, "n0 n1 n2: jump if n0 < n1, see JMPU"),
JAL (0xff27, "n0 n1 n2: jump if n0 < n1, see JMPA"),
JDL (0xff28, "n0 n1 n2: jump if n0 < n1, see JMPD"),
JUL (0xff26, "n0 n1 addr: jump if n0 < n1, see JMPU"),
JAL (0xff27, "n0 n1 addr: jump if n0 < n1, see JMPA"),
JDL (0xff28, "n0 n1 addr: jump if n0 < n1, see JMPD"),
JGE (0xff29, "Alias of JUGE"), // jump if >=
JUGE(0xff29, "n0 n1 n2: jump if n0 >= n1, see JMPU"),
JAGE(0xff2a, "n0 n1 n2: jump if n0 >= n1, see JMPA"),
JDGE(0xff2b, "n0 n1 n2: jump if n0 >= n1, see JMPD"),
JUGE(0xff29, "n0 n1 addr: jump if n0 >= n1, see JMPU"),
JAGE(0xff2a, "n0 n1 addr: jump if n0 >= n1, see JMPA"),
JDGE(0xff2b, "n0 n1 addr: jump if n0 >= n1, see JMPD"),
JLE (0xff2c, "Alias of JULE"), // jump if <=
JULE(0xff2c, "n0 n1 n2: jump if n0 <= n1, see JMPU"),
JALE(0xff2d, "n0 n1 n2: jump if n0 <= n1, see JMPA"),
JDLE(0xff2e, "n0 n1 n2: jump if n0 <= n1, see JMPD"),
JULE(0xff2c, "n0 n1 addr: jump if n0 <= n1, see JMPU"),
JALE(0xff2d, "n0 n1 addr: jump if n0 <= n1, see JMPA"),
JDLE(0xff2e, "n0 n1 addr: jump if n0 <= n1, see JMPD"),
// value compare
VCMP(0xff2f, "n0 n1: performs multiple comparissons of n0 and n1"),
// power
ZPWR(0xffff, "Power off"), // power off
;
......
......@@ -16,16 +16,13 @@ public abstract class BaseDevice extends BaseMemory implements IDevice {
board = system;
}
@Override public void memIrq(short addr) {
if ( 0 <= addr && addr <= memory.length ) { exec(); }
}
protected void sendIrq() {
int addr = memory.length - 1;
sendIrq(memory[addr]);
}
@Override public void sendIrq(byte irq) { }
@Override public void recvIrq(byte irq) { }
@Override public short length() { return (short)memory.length; }
......
......@@ -26,13 +26,7 @@ public abstract class BaseMemory implements IMemory {
memory[0xffff & addr] = data;
}
public final void copy(int addrSrc, int addrDest, IMemory dest) { copy((short)addrSrc, (short)addrDest, dest); }
@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 memIrq(short addr, byte irq) { }
@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 {
IMemory id;
short a;
byte i;
public HardwareMemIrq(IMemory device, short addr) {
public HardwareMemIrq(IMemory device, short addr, byte irq) {
id = device;
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;
*
* @author jlhawkwell
*/
public class HardwareSendIrq extends TimerTask {
public class HardwareRecvIrq extends TimerTask {
IDevice id;
byte i;
public HardwareSendIrq(IDevice device, byte irq) {
public HardwareRecvIrq(IDevice device, byte irq) {
id = device;
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 {
case 2: cref = (short)(0x0030 & ref); break;
case 3: cref = (short)(0x00c0 & ref); break;
}
switch (cref) {
case 0x0000: output = values[pos]; break;
case 0x0001: case 0x0004: case 0x0010: case 0x0040:
......@@ -55,10 +56,14 @@ public class ValueHelper {
case 2: cref = (short)(0x0030 & 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) {
case 0x0000:
case 0x0001: case 0x0004: case 0x0010: case 0x0040:
output[reg] = data; break;
case 0x0000:
case 0x0002: case 0x0008: case 0x0020: case 0x0080:
MemHelper.writeByte(values[pos], data, memory); break;
case 0x0003: case 0x000c: case 0x0030: case 0x00c0:
......@@ -109,10 +114,16 @@ public class ValueHelper {
case 2: cref = (short)(0x0030 & 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) {
case 0x0000:
case 0x0001: case 0x0004: case 0x0010: case 0x0040:
output[reg] = data; break;
case 0x0000:
case 0x0002: case 0x0008: case 0x0020: case 0x0080:
MemHelper.writeShort(values[pos], data, memory); break;
case 0x0003: case 0x000c: case 0x0030: case 0x00c0:
......
......@@ -10,8 +10,8 @@ public enum ValueType {
AD(2),
AR(3);
int t;
private ValueType(int type) { t = type; }
short t;
private ValueType(int type) { t = (short)type; }
public static ValueType valueOf(int value, int position) {
int temp = value >> (position * 2);
......@@ -24,5 +24,5 @@ public enum ValueType {
}
return D;
}
public int getValue() { return t; }
public short getValue() { return t; }
}
......@@ -2,9 +2,9 @@ movs $0 r2
add r0 16
add r2 1
movs $0 r2
jdl r0 512 2a,16
jdl r0 512 20,16+a,16
deva 0
deva 1
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!