package elw.dp.mips; import gnu.trove.TIntArrayList; import org.akraievoy.base.Die; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class DataPath { private final Instructions instructions = new Instructions(); private final Memory memory = new Memory(); private final Registers registers = new Registers(); private final Alu alu = new Alu(); private final InstructionContext ctx; private int stepsToWipeHiLo = -1; public DataPath() { ctx = new InstructionContext(instructions, memory, registers); } public Instruction execute() { instructions.resetAccess(); memory.resetAccess(); registers.resetAccess(); final int pc = registers.getReg(Reg.pc); if (!instructions.hasInstruction(pc)) { return null; } final Instruction instruction = instructions.get(pc); if (instruction != null) { ctx.setInstruction(instruction); final Method method; try { method = alu.getClass().getMethod(instruction.getOpName(), InstructionContext.class); } catch (NoSuchMethodException e) { throw Die.ifReached(e); } try { method.invoke(alu, ctx); } catch (IllegalAccessException e) { throw Die.ifReached(e); } catch (InvocationTargetException e) { throw Die.ifReached(e); } } final TIntArrayList writeRegs = registers.getWriteRegs(); final TIntArrayList readRegs = registers.getReadRegs(); final boolean hiLoWritten = writeRegs.contains(Reg.hi.ordinal()) || writeRegs.contains(Reg.lo.ordinal()); final boolean hiLoRead = readRegs.contains(Reg.hi.ordinal()) || readRegs.contains(Reg.lo.ordinal()); if (hiLoWritten) { stepsToWipeHiLo = 2; } else if (hiLoRead && stepsToWipeHiLo > 0) { stepsToWipeHiLo--; } if (!hiLoWritten && (!hiLoRead || stepsToWipeHiLo == 0)) { registers.unset(new int[]{Reg.hi.ordinal(), Reg.lo.ordinal()}); stepsToWipeHiLo = -1; } instructions.updateMinStack(registers.getRegInternal(Reg.sp)); return instruction; } public Instructions getInstructions() { return instructions; } public Memory getMemory() { return memory; } public Registers getRegisters() { return registers; } public Alu getAlu() { return alu; } public InstructionContext getCtx() { return ctx; } public void reset() { } }