Commit a3a1cc32 by Jessica Hawkwell

Fleshed out the MCU, have one weird MOVS bug

1 parent 0cbce396
Pipeline #209 passed
in 1 minute 6 seconds
...@@ -99,6 +99,11 @@ ...@@ -99,6 +99,11 @@
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.testng</groupId> <groupId>org.testng</groupId>
<artifactId>testng</artifactId> <artifactId>testng</artifactId>
<version>6.8.7</version> <version>6.8.7</version>
...@@ -109,6 +114,10 @@ ...@@ -109,6 +114,10 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
</dependency>
<dependency>
<groupId>org.testng</groupId> <groupId>org.testng</groupId>
<artifactId>testng</artifactId> <artifactId>testng</artifactId>
<scope>test</scope> <scope>test</scope>
...@@ -153,7 +162,8 @@ ...@@ -153,7 +162,8 @@
<addClasspath>true</addClasspath> <addClasspath>true</addClasspath>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries> <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
<classpathLayoutType>repository</classpathLayoutType> <classpathLayoutType>simple</classpathLayoutType>
<classpathPrefix>dependency/</classpathPrefix>
<mainClass>me.felinewith.kcpu.Kemulator</mainClass> <mainClass>me.felinewith.kcpu.Kemulator</mainClass>
</manifest> </manifest>
</archive> </archive>
......
...@@ -6,29 +6,71 @@ package me.felinewith.kcpu; ...@@ -6,29 +6,71 @@ package me.felinewith.kcpu;
*/ */
public class Converter { public class Converter {
// convert bytes to stuff // convert byte
public static short byte2short(byte[] input) { public static short byte2short(byte input) { return new Byte(input).shortValue(); }
return (short)(0xffff & arrayAdder(byteShifterUp(input))); public static int byte2int(byte input) { return new Byte(input).intValue(); }
} public static float byte2float(byte input) { return new Byte(input).floatValue(); }
public static double byte2double(byte input) { return new Byte(input).doubleValue(); }
public static int byte2int(byte[] input) { // convert short
return arrayAdder(byteShifterUp(input)); public static byte short2byte(short input) { return new Short(input).byteValue(); }
} public static int short2int(short input) { return new Short(input).intValue(); }
public static float short2float(short input) { return new Short(input).floatValue(); }
public static double short2double(short input) { return new Short(input).doubleValue(); }
// convert stuff to bytes // convert int
public static byte[] short2byte(short input) { public static byte int2byte(int input) { return new Integer(input).byteValue(); }
return byteShifterDown(input, 2); public static short int2short(int input) { return new Integer(input).shortValue(); }
} public static float int2float(int input) { return new Integer(input).floatValue(); }
public static double int2double(int input) { return new Integer(input).doubleValue(); }
// convert float
public static byte float2byte(float input) { return new Float(input).byteValue(); }
public static short float2short(float input) { return new Float(input).shortValue(); }
public static int float2int(float input) { return new Float(input).intValue(); }
public static double float2double(float input) { return new Float(input).doubleValue(); }
// convert double
public static byte double2byte(double input) { return new Double(input).byteValue(); }
public static short double2short(double input) { return new Double(input).shortValue(); }
public static int double2int(double input) { return new Double(input).intValue(); }
public static float double2float(double input) { return new Double(input).floatValue(); }
// plural -> single
// convert byte
public static short bytes2short(byte[] input) { return new Integer(byteShifterUp(input)).shortValue(); }
public static int bytes2int(byte[] input) { return byteShifterUp(input); }
public static float bytes2float(byte[] input) { return new Integer(byteShifterUp(input)).floatValue(); }
public static double bytes2double(byte[] input) { return new Integer(byteShifterUp(input)).doubleValue(); }
// convert short
public static int shorts2int(short[] input) { return shortShifterUp(input); }
public static float shorts2float(short[] input) { return new Integer(shortShifterUp(input)).floatValue(); }
public static double shorts2double(short[] input) { return new Integer(shortShifterUp(input)).doubleValue(); }
// single -> plural
// convert short
public static byte[] short2bytes(short input) { return byteShifterDown(input, 2); }
public static byte[] int2byte(int input) { // convert int
return byteShifterDown(input, 4); public static byte[] int2bytes(int input) { return byteShifterDown(input, 4); }
public static short[] int2shorts(int input) { return shortShifterDown(input); }
private static int shortShifterUp(short[] input) {
return ((0xffff & input[0]) << 16) + (0xffff & input[1]);
}
private static short[] shortShifterDown(int input) {
return new short[] {
(short)((0xffff0000 & input) >> 16),
(short)(0xffff & input)
};
} }
private static int[] byteShifterUp(byte[] input) { private static int byteShifterUp(byte[] input) {
int a = input.length; int a;
int[] temp = new int[a]; int temp = 0;
for (a = 0; a < input.length; a++) { for (a = 0; a < input.length; a++) {
temp[a] = (0xff & input[a]) << (a * 8); temp += (0xff & input[a]) << (a * 8);
} }
return temp; return temp;
} }
...@@ -46,14 +88,5 @@ public class Converter { ...@@ -46,14 +88,5 @@ public class Converter {
return temp; return temp;
} }
private static int arrayAdder(int[] input) {
int a;
int output = 0;
for (a = 0; a < input.length; a++) {
output += input[a];
}
return output;
}
private Converter() {} private Converter() {}
} }
...@@ -237,16 +237,36 @@ public class KBoard extends BaseDevice implements IMemory { ...@@ -237,16 +237,36 @@ public class KBoard extends BaseDevice implements IMemory {
} }
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"));
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 - 12; int max = mem.length;
int a; int a;
for (a = 0; a < max; a += 12) { int b;
fw.write(String.format("[%04x] %02x%02x : ", a, mem[a], mem[a + 1])); int outputter = 0;
fw.write(String.format("%02x%02x -> ", mem[a + 2], mem[a + 3])); boolean printer = false;
for (a = 0; a < max; a += 16) {
printer = false;
for (b = 0; b < 16; b++) {
if (mem[a + b] != 0) { printer = true; break; }
}
if (printer) {
if (outputter % 8 == 0) {
fw.write(String.format("[----] "));
fw.write(String.format("%-4x %-4x ", 0, 2));
fw.write(String.format("%-4x %-4x ", 4, 6));
fw.write(String.format("%-4x %-4x ", 8, 10));
fw.write(String.format("%-4x %x\n", 12, 14));
}
fw.write(String.format("[%04x] %02x%02x ", a, mem[a], mem[a + 1]));
fw.write(String.format("%02x%02x ", mem[a + 2], mem[a + 3]));
fw.write(String.format("%02x%02x ", mem[a + 4], mem[a + 5])); fw.write(String.format("%02x%02x ", mem[a + 4], mem[a + 5]));
fw.write(String.format("%02x%02x ", mem[a + 6], mem[a + 7])); fw.write(String.format("%02x%02x ", mem[a + 6], mem[a + 7]));
fw.write(String.format("%02x%02x ", mem[a + 8], mem[a + 9])); fw.write(String.format("%02x%02x ", mem[a + 8], mem[a + 9]));
fw.write(String.format("%02x%02x\n", mem[a + 10], mem[a + 11])); fw.write(String.format("%02x%02x ", mem[a + 10], mem[a + 11]));
fw.write(String.format("%02x%02x ", mem[a + 12], mem[a + 13]));
fw.write(String.format("%02x%02x\n", mem[a + 14], mem[a + 15]));
outputter++;
}
} }
if ( a < mem.length ) { if ( a < mem.length ) {
while (a < mem.length) { while (a < mem.length) {
...@@ -261,9 +281,9 @@ public class KBoard extends BaseDevice implements IMemory { ...@@ -261,9 +281,9 @@ public class KBoard extends BaseDevice implements IMemory {
catch (IOException x) {} catch (IOException x) {}
f = new File(filename.concat(".mem.bin")); f = new File(filename.concat(".mem.bin"));
try { System.out.println(String.format("Writing %s", f.getCanonicalPath())); } catch (IOException x) {}
try (FileOutputStream fos = new FileOutputStream(f)) { try (FileOutputStream fos = new FileOutputStream(f)) {
if (mem.length <= 4096) { if (mem.length <= 4096) {
System.err.println(String.format("%s Writing %d bytes...", filename, mem.length));
fos.write(mem); fos.write(mem);
} }
else { else {
...@@ -272,12 +292,10 @@ public class KBoard extends BaseDevice implements IMemory { ...@@ -272,12 +292,10 @@ public class KBoard extends BaseDevice implements IMemory {
byte[] temp; byte[] temp;
for (a = 0; a < max; a += 4096) { for (a = 0; a < max; a += 4096) {
temp = Arrays.copyOfRange(mem, a, a + 4096); temp = Arrays.copyOfRange(mem, a, a + 4096);
System.err.println(String.format("%s Writing %d bytes...", filename, temp.length));
fos.write(temp); fos.write(temp);
} }
if ( a < mem.length ) { if ( a < mem.length ) {
temp = Arrays.copyOfRange(mem, a, mem.length); temp = Arrays.copyOfRange(mem, a, mem.length);
System.err.println(String.format("%s Writing %d bytes...", filename, temp.length));
fos.write(temp); fos.write(temp);
} }
} }
......
...@@ -8,7 +8,14 @@ import java.io.FileOutputStream; ...@@ -8,7 +8,14 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.PrintStream; import java.io.PrintStream;
import me.felinewith.kcpu.hardware.KcmpOpCodes;
import me.felinewith.kcpu.opcodes.OpDirector; import me.felinewith.kcpu.opcodes.OpDirector;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
/** /**
* *
...@@ -17,8 +24,51 @@ import me.felinewith.kcpu.opcodes.OpDirector; ...@@ -17,8 +24,51 @@ import me.felinewith.kcpu.opcodes.OpDirector;
public class Kasm { public class Kasm {
private static PrintStream outer; private static PrintStream outer;
private static boolean verbose = false;
public static void main(String[] args) { public static void main(String[] args) {
setOuter(System.out); setOuter(System.out);
Options opts = new Options();
opts.addOption("b", "base", true, "Base address for binary");
opts.addOption("co", "cpu-opcodes", false, "Displays supported CPU opcodes");
opts.addOption("mo", "mcu-opcodes", false, "Displays supported MCU opcodes");
opts.addOption("v", "verbose", false, "Verbose output.");
opts.addOption("kasm", false, "Ignored.");
opts.addOption("help", "Show this help");
CommandLineParser parser = new DefaultParser();
try {
CommandLine cli = parser.parse(opts, args);
if (cli.hasOption("help") || cli.hasOption("co") || cli.hasOption("mo")) {
if (cli.hasOption("help")) {
HelpFormatter hf = new HelpFormatter();
hf.printHelp("kasm [options] [kasm ...]", "", opts,"Non-KASM files may be ignored.", false);
}
if (cli.hasOption("co")) {
logln("Supported CPU Opcodes:");
for (OpDirector oc : OpDirector.values()) {
logln("\t%04x -> [%10s]", oc.getOpcode(), oc.name());
}
logln("");
}
if (cli.hasOption("mo")) {
logln("Supported CPU Opcodes:");
for (KcmpOpCodes oc : KcmpOpCodes.values()) {
logln("\t%04x -> [%10s]", oc.getOpcode(), oc.name());
}
logln("");
}
return;
}
if (cli.hasOption("v")) { verbose = true; }
}
catch (ParseException x) {
logln("Parser error: %s", x.getMessage());
HelpFormatter hf = new HelpFormatter();
hf.printHelp("kasm [options] [kasm files]", "Header",opts,"Footer\nNote: Non-KASM text files may be ignored.", true);
return;
}
for (String a : args) { for (String a : args) {
if ( a.endsWith(".kasm") ) { if ( a.endsWith(".kasm") ) {
try { assemble(a); } try { assemble(a); }
...@@ -66,33 +116,38 @@ public class Kasm { ...@@ -66,33 +116,38 @@ public class Kasm {
parts[0] = parts[0].toUpperCase(); parts[0] = parts[0].toUpperCase();
opcode = OpDirector.valueOf(parts[0]); opcode = OpDirector.valueOf(parts[0]);
log("[%10s] ", opcode.name()); if (verbose) { log("[%10s] ", opcode.name()); }
writeShort(baos, opcode.getOpcode()); writeShort(baos, opcode.getOpcode());
log(" : "); if (verbose) { log(" : "); }
if (parts.length >= 2) { ref += asmType(parts[1]); } if (parts.length >= 2) { ref += asmType(parts[1]); }
if (parts.length >= 3) { ref += (short)(asmType(parts[2]) << 4); } if (parts.length >= 3) { ref += (short)(asmType(parts[2]) << 2); }
if (parts.length >= 4) { ref += (short)(asmType(parts[3]) << 8); } if (parts.length >= 4) { ref += (short)(asmType(parts[3]) << 4); }
if (parts.length >= 5) { ref += (short)(asmType(parts[4]) << 12); } if (parts.length >= 5) { ref += (short)(asmType(parts[4]) << 6); }
if (parts.length >= 5) { ref += 0x0400; }
else if (parts.length >= 4) { ref += 0x0300; }
else if (parts.length >= 3) { ref += 0x0200; }
else if (parts.length >= 2) { ref += 0x0100; }
writeShort(baos, ref); writeShort(baos, ref);
log(" -> "); if (verbose) { log(" -> "); }
if (parts.length >= 2) { writeShort(baos, numberize(parts[1])); } else { writeShort(baos, (short)0); } if (parts.length >= 2) { writeShort(baos, numberize(parts[1])); }
if (parts.length >= 3) { writeShort(baos, numberize(parts[2])); } else { writeShort(baos, (short)0); } if (parts.length >= 3) { writeShort(baos, numberize(parts[2])); }
if (parts.length >= 4) { writeShort(baos, numberize(parts[3])); } else { writeShort(baos, (short)0); } if (parts.length >= 4) { writeShort(baos, numberize(parts[3])); }
if (parts.length >= 5) { writeShort(baos, numberize(parts[4])); } else { writeShort(baos, (short)0); } if (parts.length >= 5) { writeShort(baos, numberize(parts[4])); }
logln(""); if (verbose) { logln(""); }
} }
return baos.toByteArray(); return baos.toByteArray();
} }
static void writeShort(ByteArrayOutputStream baos, short value) { static void writeShort(ByteArrayOutputStream baos, short value) {
byte[] temp = Converter.short2byte(value); byte[] temp = Converter.short2bytes(value);
log("%02x%02x ", temp[0], temp[1]); if (verbose) { log("%02x%02x ", temp[0], temp[1]); }
baos.write(temp, 0, temp.length); baos.write(temp, 0, temp.length);
} }
static void writeShort(FileOutputStream fos, short value) throws IOException { static void writeShort(FileOutputStream fos, short value) throws IOException {
byte[] v = Converter.short2byte(value); byte[] v = Converter.short2bytes(value);
log("[%02x%02x]", v[0], v[1]); if (verbose) { log("[%02x%02x]", v[0], v[1]); }
fos.write(v); fos.write(v);
} }
......
...@@ -53,10 +53,6 @@ public class Kcpu extends BaseDevice { ...@@ -53,10 +53,6 @@ public class Kcpu extends BaseDevice {
@Override public void init(IMemory system) { @Override public void init(IMemory system) {
setOuter(System.err); setOuter(System.err);
OpDirector[] list = OpDirector.values();
for (OpDirector od : list) {
logln("[%10s] %04x", od.name(), od.getOpcode());
}
} }
@Override public void exec() { workCycle(); } @Override public void exec() { workCycle(); }
...@@ -70,18 +66,20 @@ public class Kcpu extends BaseDevice { ...@@ -70,18 +66,20 @@ public class Kcpu extends BaseDevice {
@Override public void copy(short addrSrc, short addrDest, IMemory dest) { } @Override public void copy(short addrSrc, short addrDest, IMemory dest) { }
@Override public void memIrq(short addr) { @Override public void memIrq(short addr) {
if ( 0 <= addr && addr <= memory.length ) { exec(); } if (0 <= addr && addr <= memory.length) { exec(); }
} }
public int workCycle() { public int workCycle() {
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[4];
values[0] = MemHelper.readShort(pc + 4, kboard); switch (0x0700 & ref) {
values[1] = MemHelper.readShort(pc + 6, kboard); case 0x0400: values[3] = MemHelper.readShort(pc + 10, kboard);
values[2] = MemHelper.readShort(pc + 8, kboard); case 0x0300: values[2] = MemHelper.readShort(pc + 8, kboard);
values[3] = MemHelper.readShort(pc + 10, kboard); case 0x0200: values[1] = MemHelper.readShort(pc + 6, kboard);
case 0x0100: values[0] = MemHelper.readShort(pc + 4, kboard);
}
OpDirector od = null; OpDirector od = null;
for (OpDirector o : OpDirector.values()) { for (OpDirector o : OpDirector.values()) {
...@@ -91,29 +89,32 @@ public class Kcpu extends BaseDevice { ...@@ -91,29 +89,32 @@ public class Kcpu extends BaseDevice {
} }
} }
logln("%04x : [%10s] %04x %04x -> %04x %04x %04x %04x", log("%04x : [%10s] %04x %04x ->", pc, ((od == null)?"nop":od.name()), inst, ref);
pc, ((od == null)?"nop":od.name()), inst, ref, values[0], values[1], values[2], values[3]
); log(" %04x %04x %04x %04x\t\t", registers[0], registers[1], registers[2], registers[3]);
if ( od == null ) { pc += 12; return 0; } // inc if nop if ((0x0700 & ref) >= 0x0100) { log(" %04x", values[0]); }
if ((0x0700 & ref) >= 0x0200) { log(" %04x", values[1]); }
if ((0x0700 & ref) >= 0x0300) { log(" %04x", values[2]); }
if ((0x0700 & ref) >= 0x0400) { log(" %04x", values[3]); }
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);
pc += 12;
return 0; return 0;
} }
pc += 12; short data = ValueHelper.readShort(0, ref, registers, values, kboard);
short data;
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 0;
case DEVD: kboard.detachDevice(data); return 0; case DEVD: kboard.detachDevice(data); return 0;
case DEVM: case DEVM:
short d2 = ValueHelper.readShort(1, ref, registers, values, kboard); kboard.setDeviceRange(data, ValueHelper.readShort(1, ref, registers, values, kboard));
kboard.setDeviceRange(data, d2);
return 0; return 0;
case DEVP: case DEVP:
KMemoryRange kmr = kboard.getDeviceRange(data); KMemoryRange kmr = kboard.getDeviceRange(data);
...@@ -129,9 +130,40 @@ public class Kcpu extends BaseDevice { ...@@ -129,9 +130,40 @@ public class Kcpu extends BaseDevice {
case JMP: pc = (short)(pc + (0xffff & data)); return 0; case JMP: pc = (short)(pc + (0xffff & data)); return 0;
case JMPA: pc = data; return 0; case JMPA: pc = data; return 0;
case JMPD: pc = (short)(pc - (0xffff & data)); return 0; case JMPD: pc = (short)(pc - (0xffff & data)); return 0;
case GPC:
registers = ValueHelper.writeShort(0, ref, registers, values, board, pc);
return 0;
case ZPWR: return 0xff; case ZPWR: return 0xff;
} }
short data2 = ValueHelper.readShort(1, ref, registers, values, kboard);
short data3 = ValueHelper.readShort(2, ref, registers, values, board);
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 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; return 0;
} }
......
...@@ -11,7 +11,6 @@ public class Kemulator { ...@@ -11,7 +11,6 @@ public class Kemulator {
KBoard kb = new KBoard(); KBoard kb = new KBoard();
Buffer bb = new Buffer(); Buffer bb = new Buffer();
for (String s : args) { System.out.println(String.format("\t%s", s)); }
if ( args.length != 0 ) { if ( args.length != 0 ) {
for (String s : args) { for (String s : args) {
if (s.equals("-kasm")) { Kasm.main(args); return; } if (s.equals("-kasm")) { Kasm.main(args); return; }
......
...@@ -12,11 +12,66 @@ public enum KcmpOpCodes { ...@@ -12,11 +12,66 @@ public enum KcmpOpCodes {
MUL(0x0003), MUL(0x0003),
DIV(0x0004), DIV(0x0004),
// math library
ABS (0x0010),
ACOS (0x0011),
ASIN (0x0012),
ATAN (0x0013),
ATAN2(0x0014),
CBRT (0x0015),
CEIL (0x0016),
COS (0x0017),
COSH (0x0018),
EXP (0x0019),
EXPM1(0x001a),
FLR (0x001b),
FDIV (0x001c),
FMOD (0x001d),
GEXP (0x001e),
HYPOT(0x001f),
IEEER(0x0020),
LOG (0x0021),
LOG10(0x0022),
LOG1P(0x0023),
MAX (0x0024),
MIN (0x0025),
NEXTA(0x0026),
NEXTD(0x0027),
NEXTU(0x0028),
POW (0x0029),
RAND (0x002a),
RINT (0x002b),
ROUND(0x002c),
SCALB(0x002d),
SIGNM(0x002e),
SIN (0x002f),
SINH (0x0030),
SQRT (0x0031),
TAN (0x0032),
TANH (0x0033),
TDEG (0x0034),
TRAD (0x0035),
ULP (0x0036),
// everything here is same as above // conversions
; VC2B (0x0080),
VC2S (0x0081),
VC2I (0x0082),
VC2F (0x0083),
VL2B (0x0084),
VL2S (0x0085),
VL2I (0x0086),
VL2F (0x0087),
short o; // bitwise operations
AND(0x0090),
OR(0x0091),
XOR(0x0092),
BSU(0x0093), BSL(0x0093),
BSD(0x0094), BSR(0x0094)
;
private short o;
private KcmpOpCodes(short opcode) { o = opcode; } private KcmpOpCodes(short opcode) { o = opcode; }
private KcmpOpCodes(int opcode) { o = (short)(0xffff & opcode); } private KcmpOpCodes(int opcode) { o = (short)(0xffff & opcode); }
......
package me.felinewith.kcpu.hardware;
/**
*
* @author jlhawkwell
*/
public class KmcpOp {
private KcmpOpCodes oc;
private KmcpValueType operation;
public KmcpOp(short opcode) {
short tmpcode;
oc = null;
// decode the opcode
tmpcode = (short)(0x00ff & opcode);
for (KcmpOpCodes t : KcmpOpCodes.values()) {
if (t.getOpcode() == tmpcode) {
oc = t;
break;
}
}
// decode the operation
tmpcode = (short)((0xf000 & opcode) >> 8);
for (KmcpValueType t : KmcpValueType.values()) {
if (t.mask() == tmpcode) {
operation = t;
break;
}
}
}
public KcmpOpCodes getOpCode() {
if (oc == null) { return null; }
return oc;
}
public KmcpValueType getOperation() { return operation; }
public String name() {
if (oc == null) { return null; }
return oc.name();
}
}
package me.felinewith.kcpu.hardware;
/**
*
* @author jlhawkwell
*/
public enum KmcpValueType {
VTBYTE(0x0001),
VTSHORT(0x0002),
VTINT(0x0003),
VTFLOAT(0x0004),
;
private short m;
private KmcpValueType(short mask) { m = mask; }
private KmcpValueType(int mask) { m = (short)(0xffff & mask); }
public short mask() { return m; }
}
...@@ -12,26 +12,51 @@ import me.felinewith.kcpu.util.BaseMemory; ...@@ -12,26 +12,51 @@ 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;
public BootRom() { public BootRom() {
writepos = 0; writepos = 0;
prev = 0;
prev2 = 0;
writable = false;
memory = new byte[0x1000]; memory = new byte[0x1000];
Arrays.fill(memory, (byte)0xff); Arrays.fill(memory, (byte)0xff);
// hardcoding some bootrom // hardcoding some bootrom
// clearing the registers is as close to a reset as we can get writeBytes(Kasm.compile("movs $0 r2"));
writeBytes(Kasm.compile("movs r0 0")); writeBytes(Kasm.compile("movs 10,16 1"));
writeBytes(Kasm.compile("movs r1 0"));
writeBytes(Kasm.compile("movs r2 0")); writeBytes(Kasm.compile("add r0 16"));
writeBytes(Kasm.compile("movs r3 0")); writeBytes(Kasm.compile("add r2 1"));
writeBytes(Kasm.compile("movs $0 r2"));
writeBytes(Kasm.compile("jdl r0 512 2a,16"));
//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("mov ff00,16 61,16")); writeBytes(Kasm.compile("mov ff00,16 61,16"));
writeBytes(Kasm.compile("irqm ff01,16")); writeBytes(Kasm.compile("irqm ff01,16"));
} }
@Override public void write(short offset, byte data) { } @Override public void memIrq(short addr) {
if ((prev2 == 0x4b63) && (prev == 0x7075) && (addr == 0x7f)) { writable = true; }
else { writable = false; }
if ((0xff & prev) == 0) { prev += addr; }
else if ((0xff00 & prev) == 0) { prev = (short)(prev << 8); prev += addr; }
else { prev2 = prev; }
}
@Override public void write(short addr, byte data) {
if (!writable) { return; }
super.write(addr, data);
}
private void writeInt(int input) { private void writeInt(int input) {
byte[] data = Converter.int2byte(input); byte[] data = Converter.int2bytes(input);
writeByte(data[3]); writeByte(data[3]);
writeByte(data[2]); writeByte(data[2]);
writeByte(data[1]); writeByte(data[1]);
...@@ -42,7 +67,7 @@ public class BootRom extends BaseMemory { ...@@ -42,7 +67,7 @@ public class BootRom extends BaseMemory {
private void writeShort(int input) { writeShort((short)(0xffff & input)); } private void writeShort(int input) { writeShort((short)(0xffff & input)); }
private void writeShort(short input) { private void writeShort(short input) {
byte[] data = Converter.short2byte(input); byte[] data = Converter.short2bytes(input);
writeByte(data[1]); writeByte(data[1]);
writeByte(data[0]); writeByte(data[0]);
} }
......
...@@ -25,7 +25,7 @@ public class MemHelper { ...@@ -25,7 +25,7 @@ public class MemHelper {
byte[] data = new byte[2]; byte[] data = new byte[2];
data[0] = memory.read(addr); data[0] = memory.read(addr);
data[1] = memory.read((short)(addr + 1)); data[1] = memory.read((short)(addr + 1));
return Converter.byte2short(data); return Converter.bytes2short(data);
} }
public static void writeShort(int addr, int data, IMemory memory) { writeShort((short)addr, (short)data, memory); } public static void writeShort(int addr, int data, IMemory memory) { writeShort((short)addr, (short)data, memory); }
...@@ -33,7 +33,7 @@ public class MemHelper { ...@@ -33,7 +33,7 @@ public class MemHelper {
public static void writeShort(int addr, byte data, IMemory memory) { writeShort((short)addr, (short)data, memory); } public static void writeShort(int addr, byte data, IMemory memory) { writeShort((short)addr, (short)data, memory); }
public static void writeShort(short addr, int data, IMemory memory) { writeShort(addr, (short)data, memory); } public static void writeShort(short addr, int data, IMemory memory) { writeShort(addr, (short)data, memory); }
public static void writeShort(short addr, short data, IMemory memory) { public static void writeShort(short addr, short data, IMemory memory) {
byte[] dt = Converter.short2byte(data); byte[] dt = Converter.short2bytes(data);
memory.write(addr, dt[0]); memory.write(addr, dt[0]);
memory.write((short)(addr + 1), dt[1]); memory.write((short)(addr + 1), dt[1]);
} }
......
...@@ -9,20 +9,23 @@ import me.felinewith.kcpu.IMemory; ...@@ -9,20 +9,23 @@ import me.felinewith.kcpu.IMemory;
*/ */
public class BasicMath implements IHandler { public class BasicMath implements IHandler {
@Override public short[] opcode(OpDirector opcode, short ref, short pc, short[] regs, short[] values, IMemory memory) { @Override public short[] opcode(OpDirector opcode, short pc, short ref, short[] regs, short[] values, IMemory memory) {
short[] output = Arrays.copyOf(regs, regs.length); short[] out = Arrays.copyOf(regs, regs.length);
short va = ValueHelper.readShort(0, ref, output, values, memory); short va = ValueHelper.readShort(0, ref, out, values, memory);
short vb = ValueHelper.readShort(1, ref, output, values, memory); short vb = ValueHelper.readShort(1, ref, out, values, memory);
switch (opcode) { switch (opcode) {
case ADD: output[0] = (short)(va + vb); break; case ADD: out[0] = new Integer(va + vb).shortValue(); break;
case DIV: case DIV:
output[0] = (short)(va / vb); out[0] = (short)(va / vb);
output[1] = (short)(va % vb); out[1] = (short)(va % vb);
break; break;
case MUL: output[0] = (short)(va * vb); break; case MUL: out[0] = (short)(va * vb); break;
case SUB: output[0] = (short)(va - vb); break; case SUB: out[0] = (short)(va - vb); break;
} }
short output[] = Arrays.copyOf(regs, regs.length);
output = ValueHelper.writeShort(0, ref, regs, values, memory, out[0]);
output = ValueHelper.writeShort(1, ref, output, values, memory, out[1]);
return output; return output;
} }
} }
...@@ -7,5 +7,5 @@ import me.felinewith.kcpu.IMemory; ...@@ -7,5 +7,5 @@ import me.felinewith.kcpu.IMemory;
* @author jlhawkwell * @author jlhawkwell
*/ */
public interface IHandler { public interface IHandler {
public abstract short[] opcode(OpDirector opcode, short ref, short pc, short[] regs, short[] values, IMemory memory); public abstract short[] opcode(OpDirector opcode, short pc, short ref, short[] regs, short[] values, IMemory memory);
} }
...@@ -8,7 +8,7 @@ import me.felinewith.kcpu.IMemory; ...@@ -8,7 +8,7 @@ import me.felinewith.kcpu.IMemory;
* @author jlhawkwell * @author jlhawkwell
*/ */
public class Memory implements IHandler { public class Memory implements IHandler {
@Override public short[] opcode(OpDirector opcode, short ref, short pc, 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 data;
short[] output = Arrays.copyOf(regs, regs.length); short[] output = Arrays.copyOf(regs, regs.length);
......
...@@ -15,24 +15,41 @@ public enum OpDirector { ...@@ -15,24 +15,41 @@ public enum OpDirector {
DIV(0x0004, BasicMath.class), DIV(0x0004, BasicMath.class),
// memory stuffies // memory stuffies
MOV (0x0010, Memory.class), MOV (0x0010, Memory.class), MOVB(0x0010, Memory.class),
MOVB(0x0010, Memory.class),
MOVS(0x0011, Memory.class), MOVS(0x0011, Memory.class),
// cpu stuffies // cpu stuffies
DEVA(0xff00, null), // get device port from address DEVA(0xff00), // get device port from address
DEVD(0xff01, null), // detach device DEVD(0xff01), // detach device
DEVM(0xff02, null), // relocate device DEVM(0xff02), // relocate device
DEVP(0x1003, null), // get device address from port DEVP(0x1003), // get device address from port
IRQD(0xff10, null), // interrupt to port IRQD(0xff10), // interrupt to port
IRQM(0xff11, null), // interrupt to memory IRQM(0xff11), // interrupt to memory
JMP (0xff18, null), // jump up JMP (0xff18), // jump up
JMPA(0xff19, null), // jump absolute addr JMPA(0xff19), // jump absolute addr
JMPD(0xff1a, null), // jump down JMPD(0xff1a), // jump down
GPC (0xff1b), // get instruction pointer
ZPWR(0xffff, null), // power off JE (0xff20), // jump if =
JAE (0xff21),
JDE (0xff22),
JG (0xff23), // jump if >
JAG (0xff24),
JDG (0xff25),
JL (0xff26), // jump if <
JAL (0xff27),
JDL (0xff28),
JGE (0xff29), // jump if >=
JAGE(0xff2a),
JDGE(0xff2b),
JLE (0xff2c), // jump if <=
JALE(0xff2d),
JDLE(0xff2e),
VCMP(0xff2f),
ZPWR(0xffff), // power off
; ;
...@@ -46,14 +63,22 @@ public enum OpDirector { ...@@ -46,14 +63,22 @@ public enum OpDirector {
o = (short)(0xffff & opcode); o = (short)(0xffff & opcode);
c = cls; c = cls;
} }
private OpDirector(short opcode) {
o = opcode;
c = null;
}
private OpDirector(int opcode) {
o = (short)(0xffff & opcode);
c = null;
}
public short getOpcode() { return o; } public short getOpcode() { return o; }
public boolean hasHandler() { return (c != null); } public boolean hasHandler() { return (c != null); }
public short[] call(short ref, short pc, short[] regs, short[] values, IMemory memory) { public short[] call(short pc, short ref, short[] regs, short[] values, IMemory memory) {
try { try {
if (c == null) { return regs; } if (c == null) { return regs; }
IHandler ih = c.newInstance(); IHandler ih = c.newInstance();
return ih.opcode(this, ref, pc, regs, values, memory); return ih.opcode(this, pc, ref, regs, values, memory);
} }
catch (IllegalAccessException | InstantiationException e) {} catch (IllegalAccessException | InstantiationException e) {}
return regs; return regs;
......
...@@ -21,24 +21,24 @@ public class ValueHelper { ...@@ -21,24 +21,24 @@ public class ValueHelper {
// 03: register address // 03: register address
short cref = 0; short cref = 0;
switch (pos) { switch (pos) {
case 0: cref = (short)(0x000f & ref); break; case 0: cref = (short)(0x0003 & ref); break;
case 1: cref = (short)(0x00f0 & ref); break; case 1: cref = (short)(0x000c & ref); break;
case 2: cref = (short)(0x0f00 & ref); break; case 2: cref = (short)(0x0030 & ref); break;
case 3: cref = (short)(0xf000 & 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 0x0010: case 0x0100: case 0x1000: case 0x0001: case 0x0004: case 0x0010: case 0x0040:
output = regs[reg]; break; output = regs[reg]; break;
case 0x0002: case 0x0020: case 0x0200: case 0x2000: case 0x0002: case 0x0008: case 0x0020: case 0x0080:
output = MemHelper.readByte(values[pos], memory); break; output = MemHelper.readByte(values[pos], memory); break;
case 0x0003: case 0x0030: case 0x0300: case 0x3000: case 0x0003: case 0x000c: case 0x0030: case 0x00c0:
output = MemHelper.readByte(regs[reg], memory); break; output = MemHelper.readByte(regs[reg], memory); break;
} }
return output; return output;
} }
public static short[] writeByte(int pos, int ref, short[] regs, short[] values, IMemory memory, short data) { public static short[] writeByte(int pos, int ref, short[] regs, short[] values, IMemory memory, short data) {
return writeByte((short)pos, (short)ref, regs, values, memory, (byte)(0xff & data)); return writeByte((short)pos, (short)ref, regs, values, memory, (byte)(data));
} }
public static short[] writeByte(short pos, short ref, short[] regs, short[] values, IMemory memory, short data) { public static short[] writeByte(short pos, short ref, short[] regs, short[] values, IMemory memory, short data) {
return writeByte(pos, ref, regs, values, memory, (byte)(0xff & data)); return writeByte(pos, ref, regs, values, memory, (byte)(0xff & data));
...@@ -51,18 +51,18 @@ public class ValueHelper { ...@@ -51,18 +51,18 @@ public class ValueHelper {
short reg = (short)(0x03 & values[pos]); short reg = (short)(0x03 & values[pos]);
short cref = 0; short cref = 0;
switch (pos) { switch (pos) {
case 0: cref = (short)(0x000f & ref); break; case 0: cref = (short)(0x0003 & ref); break;
case 1: cref = (short)(0x00f0 & ref); break; case 1: cref = (short)(0x000c & ref); break;
case 2: cref = (short)(0x0f00 & ref); break; case 2: cref = (short)(0x0030 & ref); break;
case 3: cref = (short)(0xf000 & ref); break; case 3: cref = (short)(0x00c0 & ref); break;
} }
switch (cref) { switch (cref) {
case 0x0001: case 0x0010: case 0x0100: case 0x1000: case 0x0001: case 0x0004: case 0x0010: case 0x0040:
output[reg] = data; break; output[reg] = data; break;
case 0x0000: case 0x0000:
case 0x0002: case 0x0020: case 0x0200: case 0x2000: 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 0x0030: case 0x0300: case 0x3000: case 0x0003: case 0x000c: case 0x0030: case 0x00c0:
MemHelper.writeByte(output[reg], data, memory); break; MemHelper.writeByte(output[reg], data, memory); break;
} }
return output; return output;
...@@ -80,18 +80,18 @@ public class ValueHelper { ...@@ -80,18 +80,18 @@ public class ValueHelper {
// 03: register address // 03: register address
short cref = 0; short cref = 0;
switch (pos) { switch (pos) {
case 0: cref = (short)(0x000f & ref); break; case 0: cref = (short)(0x0003 & ref); break;
case 1: cref = (short)(0x00f0 & ref); break; case 1: cref = (short)(0x000c & ref); break;
case 2: cref = (short)(0x0f00 & ref); break; case 2: cref = (short)(0x0030 & ref); break;
case 3: cref = (short)(0xf000 & 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 0x0010: case 0x0100: case 0x1000: case 0x0001: case 0x0004: case 0x0010: case 0x0040:
output = regs[reg]; break; output = regs[reg]; break;
case 0x0002: case 0x0020: case 0x0200: case 0x2000: case 0x0002: case 0x0008: case 0x0020: case 0x0080:
output = MemHelper.readShort(values[pos], memory); break; output = MemHelper.readShort(values[pos], memory); break;
case 0x0003: case 0x0030: case 0x0300: case 0x3000: case 0x0003: case 0x000c: case 0x0030: case 0x00c0:
output = MemHelper.readShort(regs[reg], memory); break; output = MemHelper.readShort(regs[reg], memory); break;
} }
return output; return output;
...@@ -105,18 +105,18 @@ public class ValueHelper { ...@@ -105,18 +105,18 @@ public class ValueHelper {
short reg = (short)(0x03 & values[pos]); short reg = (short)(0x03 & values[pos]);
short cref = 0; short cref = 0;
switch (pos) { switch (pos) {
case 0: cref = (short)(0x000f & ref); break; case 0: cref = (short)(0x0003 & ref); break;
case 1: cref = (short)(0x00f0 & ref); break; case 1: cref = (short)(0x000c & ref); break;
case 2: cref = (short)(0x0f00 & ref); break; case 2: cref = (short)(0x0030 & ref); break;
case 3: cref = (short)(0xf000 & ref); break; case 3: cref = (short)(0x00c0 & ref); break;
} }
switch (cref) { switch (cref) {
case 0x0001: case 0x0010: case 0x0100: case 0x1000: case 0x0001: case 0x0004: case 0x0010: case 0x0040:
output[reg] = data; break; output[reg] = data; break;
case 0x0000: case 0x0000:
case 0x0002: case 0x0020: case 0x0200: case 0x2000: 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 0x0030: case 0x0300: case 0x3000: case 0x0003: case 0x000c: case 0x0030: case 0x00c0:
MemHelper.writeShort(output[reg], data, memory); break; MemHelper.writeShort(output[reg], data, memory); break;
} }
return output; return output;
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!