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 @@
<dependencyManagement>
<dependencies>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8.7</version>
......@@ -109,6 +114,10 @@
<dependencies>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
......@@ -153,7 +162,8 @@
<addClasspath>true</addClasspath>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
<classpathLayoutType>repository</classpathLayoutType>
<classpathLayoutType>simple</classpathLayoutType>
<classpathPrefix>dependency/</classpathPrefix>
<mainClass>me.felinewith.kcpu.Kemulator</mainClass>
</manifest>
</archive>
......
......@@ -6,29 +6,71 @@ package me.felinewith.kcpu;
*/
public class Converter {
// convert bytes to stuff
public static short byte2short(byte[] input) {
return (short)(0xffff & arrayAdder(byteShifterUp(input)));
}
// convert byte
public static short byte2short(byte input) { return new Byte(input).shortValue(); }
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) {
return arrayAdder(byteShifterUp(input));
}
// convert short
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
public static byte[] short2byte(short input) {
return byteShifterDown(input, 2);
}
// convert int
public static byte int2byte(int input) { return new Integer(input).byteValue(); }
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) {
return byteShifterDown(input, 4);
// convert int
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) {
int a = input.length;
int[] temp = new int[a];
private static int byteShifterUp(byte[] input) {
int a;
int temp = 0;
for (a = 0; a < input.length; a++) {
temp[a] = (0xff & input[a]) << (a * 8);
temp += (0xff & input[a]) << (a * 8);
}
return temp;
}
......@@ -46,14 +88,5 @@ public class Converter {
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() {}
}
......@@ -237,16 +237,36 @@ public class KBoard extends BaseDevice implements IMemory {
}
public void dumpMemory(String filename, byte[] 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)) {
int max = mem.length - 12;
int max = mem.length;
int a;
for (a = 0; a < max; a += 12) {
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 + 6], mem[a + 7]));
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]));
int b;
int outputter = 0;
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 + 6], mem[a + 7]));
fw.write(String.format("%02x%02x ", mem[a + 8], mem[a + 9]));
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 ) {
while (a < mem.length) {
......@@ -261,9 +281,9 @@ public class KBoard extends BaseDevice implements IMemory {
catch (IOException x) {}
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)) {
if (mem.length <= 4096) {
System.err.println(String.format("%s Writing %d bytes...", filename, mem.length));
fos.write(mem);
}
else {
......@@ -272,12 +292,10 @@ public class KBoard extends BaseDevice implements IMemory {
byte[] temp;
for (a = 0; a < max; a += 4096) {
temp = Arrays.copyOfRange(mem, a, a + 4096);
System.err.println(String.format("%s Writing %d bytes...", filename, temp.length));
fos.write(temp);
}
if ( 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);
}
}
......
......@@ -8,7 +8,14 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import me.felinewith.kcpu.hardware.KcmpOpCodes;
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;
public class Kasm {
private static PrintStream outer;
private static boolean verbose = false;
public static void main(String[] args) {
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) {
if ( a.endsWith(".kasm") ) {
try { assemble(a); }
......@@ -66,33 +116,38 @@ public class Kasm {
parts[0] = parts[0].toUpperCase();
opcode = OpDirector.valueOf(parts[0]);
log("[%10s] ", opcode.name());
if (verbose) { log("[%10s] ", opcode.name()); }
writeShort(baos, opcode.getOpcode());
log(" : ");
if (verbose) { log(" : "); }
if (parts.length >= 2) { ref += asmType(parts[1]); }
if (parts.length >= 3) { ref += (short)(asmType(parts[2]) << 4); }
if (parts.length >= 4) { ref += (short)(asmType(parts[3]) << 8); }
if (parts.length >= 5) { ref += (short)(asmType(parts[4]) << 12); }
if (parts.length >= 3) { ref += (short)(asmType(parts[2]) << 2); }
if (parts.length >= 4) { ref += (short)(asmType(parts[3]) << 4); }
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);
log(" -> ");
if (parts.length >= 2) { writeShort(baos, numberize(parts[1])); } else { writeShort(baos, (short)0); }
if (parts.length >= 3) { writeShort(baos, numberize(parts[2])); } else { writeShort(baos, (short)0); }
if (parts.length >= 4) { writeShort(baos, numberize(parts[3])); } else { writeShort(baos, (short)0); }
if (parts.length >= 5) { writeShort(baos, numberize(parts[4])); } else { writeShort(baos, (short)0); }
logln("");
if (verbose) { log(" -> "); }
if (parts.length >= 2) { writeShort(baos, numberize(parts[1])); }
if (parts.length >= 3) { writeShort(baos, numberize(parts[2])); }
if (parts.length >= 4) { writeShort(baos, numberize(parts[3])); }
if (parts.length >= 5) { writeShort(baos, numberize(parts[4])); }
if (verbose) { logln(""); }
}
return baos.toByteArray();
}
static void writeShort(ByteArrayOutputStream baos, short value) {
byte[] temp = Converter.short2byte(value);
log("%02x%02x ", temp[0], temp[1]);
byte[] temp = Converter.short2bytes(value);
if (verbose) { log("%02x%02x ", temp[0], temp[1]); }
baos.write(temp, 0, temp.length);
}
static void writeShort(FileOutputStream fos, short value) throws IOException {
byte[] v = Converter.short2byte(value);
log("[%02x%02x]", v[0], v[1]);
byte[] v = Converter.short2bytes(value);
if (verbose) { log("[%02x%02x]", v[0], v[1]); }
fos.write(v);
}
......
......@@ -53,10 +53,6 @@ public class Kcpu extends BaseDevice {
@Override public void init(IMemory system) {
setOuter(System.err);
OpDirector[] list = OpDirector.values();
for (OpDirector od : list) {
logln("[%10s] %04x", od.name(), od.getOpcode());
}
}
@Override public void exec() { workCycle(); }
......@@ -70,18 +66,20 @@ public class Kcpu extends BaseDevice {
@Override public void copy(short addrSrc, short addrDest, IMemory dest) { }
@Override public void memIrq(short addr) {
if ( 0 <= addr && addr <= memory.length ) { exec(); }
if (0 <= addr && addr <= memory.length) { exec(); }
}
public int workCycle() {
if ( pc >= 0xfff0 ) { pc = 0; }
if (pc >= 0xfff0) { pc = 0; }
short inst = MemHelper.readShort(pc, kboard);
short ref = MemHelper.readShort(pc + 2, kboard);
short[] values = new short[4];
values[0] = MemHelper.readShort(pc + 4, kboard);
values[1] = MemHelper.readShort(pc + 6, kboard);
values[2] = MemHelper.readShort(pc + 8, kboard);
values[3] = MemHelper.readShort(pc + 10, kboard);
switch (0x0700 & ref) {
case 0x0400: values[3] = MemHelper.readShort(pc + 10, kboard);
case 0x0300: values[2] = MemHelper.readShort(pc + 8, kboard);
case 0x0200: values[1] = MemHelper.readShort(pc + 6, kboard);
case 0x0100: values[0] = MemHelper.readShort(pc + 4, kboard);
}
OpDirector od = null;
for (OpDirector o : OpDirector.values()) {
......@@ -91,29 +89,32 @@ public class Kcpu extends BaseDevice {
}
}
logln("%04x : [%10s] %04x %04x -> %04x %04x %04x %04x",
pc, ((od == null)?"nop":od.name()), inst, ref, values[0], values[1], values[2], values[3]
);
log("%04x : [%10s] %04x %04x ->", pc, ((od == null)?"nop":od.name()), inst, ref);
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() ) {
registers = od.call(pc, ref, registers, values, kboard);
pc += 12;
return 0;
}
pc += 12;
short data;
data = ValueHelper.readShort(0, ref, registers, values, kboard);
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 DEVM:
short d2 = ValueHelper.readShort(1, ref, registers, values, kboard);
kboard.setDeviceRange(data, d2);
kboard.setDeviceRange(data, ValueHelper.readShort(1, ref, registers, values, kboard));
return 0;
case DEVP:
KMemoryRange kmr = kboard.getDeviceRange(data);
......@@ -129,9 +130,40 @@ public class Kcpu extends BaseDevice {
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 GPC:
registers = ValueHelper.writeShort(0, ref, registers, values, board, pc);
return 0;
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;
}
......
......@@ -11,7 +11,6 @@ public class Kemulator {
KBoard kb = new KBoard();
Buffer bb = new Buffer();
for (String s : args) { System.out.println(String.format("\t%s", s)); }
if ( args.length != 0 ) {
for (String s : args) {
if (s.equals("-kasm")) { Kasm.main(args); return; }
......
......@@ -12,11 +12,66 @@ public enum KcmpOpCodes {
MUL(0x0003),
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(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;
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;
memory = new byte[0x1000];
Arrays.fill(memory, (byte)0xff);
// hardcoding some bootrom
// clearing the registers is as close to a reset as we can get
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("movs $0 r2"));
writeBytes(Kasm.compile("movs 10,16 1"));
writeBytes(Kasm.compile("add r0 16"));
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("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) {
byte[] data = Converter.int2byte(input);
byte[] data = Converter.int2bytes(input);
writeByte(data[3]);
writeByte(data[2]);
writeByte(data[1]);
......@@ -42,7 +67,7 @@ public class BootRom extends BaseMemory {
private void writeShort(int input) { writeShort((short)(0xffff & input)); }
private void writeShort(short input) {
byte[] data = Converter.short2byte(input);
byte[] data = Converter.short2bytes(input);
writeByte(data[1]);
writeByte(data[0]);
}
......
......@@ -25,7 +25,7 @@ public class MemHelper {
byte[] data = new byte[2];
data[0] = memory.read(addr);
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); }
......@@ -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(short addr, int data, IMemory memory) { writeShort(addr, (short)data, 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((short)(addr + 1), dt[1]);
}
......
......@@ -9,20 +9,23 @@ import me.felinewith.kcpu.IMemory;
*/
public class BasicMath implements IHandler {
@Override public short[] opcode(OpDirector opcode, short ref, short pc, short[] regs, short[] values, IMemory memory) {
short[] output = Arrays.copyOf(regs, regs.length);
short va = ValueHelper.readShort(0, ref, output, values, memory);
short vb = ValueHelper.readShort(1, ref, output, values, memory);
@Override public short[] opcode(OpDirector opcode, short pc, short ref, short[] regs, short[] values, IMemory memory) {
short[] out = Arrays.copyOf(regs, regs.length);
short va = ValueHelper.readShort(0, ref, out, values, memory);
short vb = ValueHelper.readShort(1, ref, out, values, memory);
switch (opcode) {
case ADD: output[0] = (short)(va + vb); break;
case ADD: out[0] = new Integer(va + vb).shortValue(); break;
case DIV:
output[0] = (short)(va / vb);
output[1] = (short)(va % vb);
out[0] = (short)(va / vb);
out[1] = (short)(va % vb);
break;
case MUL: output[0] = (short)(va * vb); break;
case SUB: output[0] = (short)(va - vb); break;
case MUL: out[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;
}
}
......@@ -7,5 +7,5 @@ import me.felinewith.kcpu.IMemory;
* @author jlhawkwell
*/
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;
* @author jlhawkwell
*/
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[] output = Arrays.copyOf(regs, regs.length);
......
......@@ -15,24 +15,41 @@ public enum OpDirector {
DIV(0x0004, BasicMath.class),
// memory stuffies
MOV (0x0010, Memory.class),
MOVB(0x0010, Memory.class),
MOV (0x0010, Memory.class), MOVB(0x0010, Memory.class),
MOVS(0x0011, Memory.class),
// cpu stuffies
DEVA(0xff00, null), // get device port from address
DEVD(0xff01, null), // detach device
DEVM(0xff02, null), // relocate device
DEVP(0x1003, null), // get device address from port
DEVA(0xff00), // get device port from address
DEVD(0xff01), // detach device
DEVM(0xff02), // relocate device
DEVP(0x1003), // get device address from port
IRQD(0xff10, null), // interrupt to port
IRQM(0xff11, null), // interrupt to memory
IRQD(0xff10), // interrupt to port
IRQM(0xff11), // interrupt to memory
JMP (0xff18, null), // jump up
JMPA(0xff19, null), // jump absolute addr
JMPD(0xff1a, null), // jump down
JMP (0xff18), // jump up
JMPA(0xff19), // jump absolute addr
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 {
o = (short)(0xffff & opcode);
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 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 {
if (c == null) { return regs; }
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) {}
return regs;
......
......@@ -21,24 +21,24 @@ public class ValueHelper {
// 03: register address
short cref = 0;
switch (pos) {
case 0: cref = (short)(0x000f & ref); break;
case 1: cref = (short)(0x00f0 & ref); break;
case 2: cref = (short)(0x0f00 & ref); break;
case 3: cref = (short)(0xf000 & ref); break;
case 0: cref = (short)(0x0003 & ref); break;
case 1: cref = (short)(0x000c & ref); break;
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 0x0010: case 0x0100: case 0x1000:
case 0x0001: case 0x0004: case 0x0010: case 0x0040:
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;
case 0x0003: case 0x0030: case 0x0300: case 0x3000:
case 0x0003: case 0x000c: case 0x0030: case 0x00c0:
output = MemHelper.readByte(regs[reg], memory); break;
}
return output;
}
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) {
return writeByte(pos, ref, regs, values, memory, (byte)(0xff & data));
......@@ -51,18 +51,18 @@ public class ValueHelper {
short reg = (short)(0x03 & values[pos]);
short cref = 0;
switch (pos) {
case 0: cref = (short)(0x000f & ref); break;
case 1: cref = (short)(0x00f0 & ref); break;
case 2: cref = (short)(0x0f00 & ref); break;
case 3: cref = (short)(0xf000 & ref); break;
case 0: cref = (short)(0x0003 & ref); break;
case 1: cref = (short)(0x000c & ref); break;
case 2: cref = (short)(0x0030 & ref); break;
case 3: cref = (short)(0x00c0 & ref); break;
}
switch (cref) {
case 0x0001: case 0x0010: case 0x0100: case 0x1000:
case 0x0001: case 0x0004: case 0x0010: case 0x0040:
output[reg] = data; break;
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;
case 0x0003: case 0x0030: case 0x0300: case 0x3000:
case 0x0003: case 0x000c: case 0x0030: case 0x00c0:
MemHelper.writeByte(output[reg], data, memory); break;
}
return output;
......@@ -80,18 +80,18 @@ public class ValueHelper {
// 03: register address
short cref = 0;
switch (pos) {
case 0: cref = (short)(0x000f & ref); break;
case 1: cref = (short)(0x00f0 & ref); break;
case 2: cref = (short)(0x0f00 & ref); break;
case 3: cref = (short)(0xf000 & ref); break;
case 0: cref = (short)(0x0003 & ref); break;
case 1: cref = (short)(0x000c & ref); break;
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 0x0010: case 0x0100: case 0x1000:
case 0x0001: case 0x0004: case 0x0010: case 0x0040:
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;
case 0x0003: case 0x0030: case 0x0300: case 0x3000:
case 0x0003: case 0x000c: case 0x0030: case 0x00c0:
output = MemHelper.readShort(regs[reg], memory); break;
}
return output;
......@@ -105,18 +105,18 @@ public class ValueHelper {
short reg = (short)(0x03 & values[pos]);
short cref = 0;
switch (pos) {
case 0: cref = (short)(0x000f & ref); break;
case 1: cref = (short)(0x00f0 & ref); break;
case 2: cref = (short)(0x0f00 & ref); break;
case 3: cref = (short)(0xf000 & ref); break;
case 0: cref = (short)(0x0003 & ref); break;
case 1: cref = (short)(0x000c & ref); break;
case 2: cref = (short)(0x0030 & ref); break;
case 3: cref = (short)(0x00c0 & ref); break;
}
switch (cref) {
case 0x0001: case 0x0010: case 0x0100: case 0x1000:
case 0x0001: case 0x0004: case 0x0010: case 0x0040:
output[reg] = data; break;
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;
case 0x0003: case 0x0030: case 0x0300: case 0x3000:
case 0x0003: case 0x000c: case 0x0030: case 0x00c0:
MemHelper.writeShort(output[reg], data, memory); break;
}
return output;
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!