Skip to main content
2 of 4
added 3714 characters in body; added 4 characters in body
Jump3r
  • 175
  • 6

Emulated CPU code

I recently started new project - a CPU emulator in Java. Base code is written, now I can start to slowly implement new things, but I want code review to be done, to reformat code before it messes up. Unfortunately, I didn't add any Javadocs and didn't do any deeper tests, except checking if basic OP codes are working.

https://github.com/jakub-gonet/Emulated-CPU

Code structure is like so:

  • CommandHelper.py - script used to convert Op code to binary form and vice versa
  • Main - entry point
  • cpu/OPCODE - list of OP codes and what they should do
  • cpu/ADDR_TYPE - addressing modes
  • cpu/StatusFlags - CPU flags (carry, negative, zero flag etc)
  • cpu/programCounter - program counter
  • cpu/CPUEmulator - main class to bind rest to it
  • cpu/instructionArgument, InstructionMnemonic, Instruction - used to encode a single instruction
  • cpu/instruction/InstructionRunner - fetch and run Instruction
  • cpu/instruction/converter - package used to convert from bits to OP code and address modes
  • cpu/memory - package used to represent CPU memory

(bolded are important)

package cpu.instruction;

import cpu.ADDR_TYPE;
import cpu.instruction.converter.ValueToAddressingMode;
import cpu.instruction.converter.ValueToOPCode;
import cpu.memory.Memory;

public class InstructionRunner {
public static void run(Instruction instruction) {
    if (instruction != null) {
        Integer arg2Value = (instruction.getArg2() != null) ? instruction.getArg2()
                                                                         .getValue() : null;

        Integer arg1Value = (instruction.getArg1() != null) ? instruction.getArg1()
                                                                         .getValue() : null;

        Integer address = (instruction.getArg1() != null) ? instruction.getArg1()
                                                                       .getAddress() : null;

        Integer value = instruction.getMnemonic()
                                   .getOpcode()
                                   .apply(arg1Value,
                                       arg2Value);

        if (instruction.getArgumentCount() > 0) instruction.getArg1()
                                                           .getMemory()
                                                           .write(address, value);
    } else throw new
        IllegalArgumentException("ERROR: Instruction can't be null.");

}

public static Instruction fetchInstruction(int address) {
    try {
        int opCodeAndAddresses = readFromMemory(address);
        InstructionMnemonic mnemonic = new InstructionMnemonic(
            ValueToOPCode.getOPCode(opCodeAndAddresses)
        );
        InstructionArgument[] arguments = createArguments(mnemonic.getRequiredArgs(), address, opCodeAndAddresses);

        return new Instruction(mnemonic, arguments[0], arguments[1]);

    } catch (IndexOutOfBoundsException e) {
        System.out.println("ERROR: OP code not recognized.");
    } catch (NullPointerException e) {
        System.out.println("ERROR: Bad format of instruction.");
    }
    return null;
}

private static InstructionArgument[] createArguments(int argumentCount, int address, int argumentsCode) {
    InstructionArgument arg2 = null;
    InstructionArgument arg1 = null;

    switch (argumentCount) {
        case 2:
            int arg2Code = readFromMemory(address + 2);
            ADDR_TYPE secondAddressType = getAddressType(2, argumentsCode);
            arg2 = new InstructionArgument(arg2Code, secondAddressType);
        case 1:
            int arg1Code = readFromMemory(address + 1);
            ADDR_TYPE firstAddressType = getAddressType(1, argumentsCode);
            arg1 = new InstructionArgument(arg1Code, firstAddressType);
    }
    return new InstructionArgument[] {arg1, arg2};
}

private static ADDR_TYPE getAddressType(int argumentNumber, int operatorAndAddressingModeCode) {
    if (argumentNumber == 1) return ValueToAddressingMode.getFirstArgAddressingMode(operatorAndAddressingModeCode);
    if (argumentNumber == 2) return ValueToAddressingMode.getSecondArgAddressingMode(operatorAndAddressingModeCode);
    throw new IllegalArgumentException("ERROR: OP code argument does not exist.");
}

private static int readFromMemory(int address) {
    return Memory.getInstance()
                 .read(address);
}
}

I mostly wonder if that null policy is good practice and how to manage exceptions in that type of project.

Jump3r
  • 175
  • 6