Last active
March 27, 2019 19:59
-
-
Save devdilson/7e36b37cae76be0a05cd3af9cce81a5e to your computer and use it in GitHub Desktop.
HypotheticalProcessor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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