Skip to content

Instantly share code, notes, and snippets.

@devdilson
Last active March 27, 2019 19:59
Show Gist options
  • Save devdilson/7e36b37cae76be0a05cd3af9cce81a5e to your computer and use it in GitHub Desktop.
Save devdilson/7e36b37cae76be0a05cd3af9cce81a5e to your computer and use it in GitHub Desktop.
HypotheticalProcessor
package net.hyprocessor;
public class HypotheticalProcessor {
public static final int MAGIC = 0xC0FFEE01;
public static final int ADD_CONSTANT_INST = 0x1;
public static final int SUB_CONSTANT_INST = 2;
private static final byte JMP_INST = 3;
public static final int OUTPUT_REG_INST = 0x4;
private CPUState state;
private byte[] memory;
private int fetchedInstruction;
class CPUState {
int eip;
int registers[] = new int[3];
boolean isRunning;
}
public HypotheticalProcessor() {
this.state = new CPUState();
}
public void loadProgram(byte[] program) {
this.memory = new byte[program.length];
System.arraycopy(program, 0, this.memory, 0, program.length);
this.state.eip = 0;
int magic = decodeInt();
log("Magic: %x valid: %s", magic, magic == MAGIC);
if (magic == MAGIC) {
state.eip += 4;
state.isRunning = true;
}
}
private int decodeInt() {
int magic = (memory[state.eip] << 24);
magic |= ((memory[state.eip + 1]) & 0xFF) << 16;
magic |= ((memory[state.eip + 2]) & 0xFF) << 8;
magic |= ((memory[state.eip + 3]) & 0xFF);
return magic;
}
public boolean isRunning() {
return state.isRunning;
}
public void fetch() {
// For simplicity instructions are always 32 bits, composed by 1 byte operand.
fetchedInstruction = decodeInt();
log("Fetched instruction %x\n", fetchedInstruction);
if (fetchedInstruction == 0) {
state.isRunning = false;
}
}
public void log(String m, Object... args) {
System.out.println(String.format(m, args));
}
public void execute() {
byte opcode = (byte) (fetchedInstruction & 0x000000FF);
byte operand = (byte) (fetchedInstruction >> 8);
short value = (short) (fetchedInstruction >> 16);
log("Executing opcode %x operand %s\n", opcode, operand);
switch (opcode) {
case ADD_CONSTANT_INST:
state.registers[operand] += value;
log("Executing add_constant %d to register %d\n", value, operand);
break;
case SUB_CONSTANT_INST:
state.registers[operand] -= value;
log("Executing sub_constant %d to register %d\n", value, operand);
break;
case OUTPUT_REG_INST:
log("Register: %d has value: %d", operand, state.registers[operand]);
break;
case JMP_INST:
state.eip = value * 4;
break;
}
state.eip += 4;
}
}
package net.hyprocessor;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
public class Main {
public static void main(String args[]) throws Exception {
HypotheticalProcessor processor = new HypotheticalProcessor();
URL url = Main.class.getClassLoader().getResource("program1");
byte[] program = Files.readAllBytes(Paths.get(url.toURI()));
processor.loadProgram(program);
while (processor.isRunning()) {
processor.fetch();
processor.execute();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment