diff --git a/src/swen90006/machine/Machine.java b/src/swen90006/machine/Machine.java index 09cbcb5dc78393ccaf62e1a4817f8f15e4b99ff4..92d3b56553b579c2419f7ff1245bcee45f1af3f8 100644 --- a/src/swen90006/machine/Machine.java +++ b/src/swen90006/machine/Machine.java @@ -3,133 +3,120 @@ package swen90006.machine; import java.util.Arrays; import java.util.List; -public class Machine { +public class Machine +{ /** arithmetic instructions each take three registers as arguments with the * destination register appearing first */ - /** - * add rd rs1 rs2 =~ rd = rs1 + rs2 - */ + /** add rd rs1 rs2 =~ rd = rs1 + rs2 */ public static final String INSTRUCTION_ADD = "add"; - /** - * sub rd rs1 rs2 =~ rd = rs1 - rs2 - */ + /** sub rd rs1 rs2 =~ rd = rs1 - rs2 */ public static final String INSTRUCTION_SUBTRACT = "sub"; - /** - * mul rd rs1 rs2 =~ rd = rs1 * rs2 - */ + /** mul rd rs1 rs2 =~ rd = rs1 * rs2 */ public static final String INSTRUCTION_MULT = "mul"; - /** - * div rd rs1 rs2 =~ rd = rs1 / rs2 - */ + /** div rd rs1 rs2 =~ rd = rs1 / rs2 */ public static final String INSTRUCTION_DIVIDE = "div"; - /** - * ret rs =~ return rs - */ + /** ret rs =~ return rs */ public static final String INSTRUCTION_RETURN = "ret"; - /** - * ldr rd rs offs =~ rd = rs[offs] - */ + /** ldr rd rs offs =~ rd = rs[offs] */ public static final String INSTRUCTION_LOAD = "ldr"; - /** - * str ra offs rb =~ ra[offs] = rb - */ + /** str ra offs rb =~ ra[offs] = rb */ public static final String INSTRUCTION_STORE = "str"; - /** - * mov rd val =~ rd = val - */ + /** mov rd val =~ rd = val */ public static final String INSTRUCTION_MOVE = "mov"; - /** - * jmp offs =~ pc = pc + offs - */ + /** jmp offs =~ pc = pc + offs */ public static final String INSTRUCTION_JUMP = "jmp"; - /** - * jz ra offs =~ if (ra == 0) pc = pc + offs else pc = pc + 1 - */ + /** jz ra offs =~ if (ra == 0) pc = pc + offs else pc = pc + 1 */ public static final String INSTRUCTION_JZ = "jz"; public static final int NUM_REGS = 32; public static final int MAX_REG = (NUM_REGS - 1); public static final int MEMORY_SIZE = 65536; /* 4 x as much memory as a 64 */ - public static final int MAX_ADDR = MEMORY_SIZE - 1; + public static final int MAX_ADDR = MEMORY_SIZE-1; private int[] memory; private int[] regs; private int count = 0; /* counts number of instructions executed so far */ - public Machine() { + public Machine() + { memory = new int[MEMORY_SIZE]; regs = new int[NUM_REGS]; count = 0; } - private void do_add(int dest, int src1, int src2) { + private void do_add(int dest, int src1, int src2) + { regs[dest] = regs[src1] + regs[src2]; } - private void do_sub(int dest, int src1, int src2) { + private void do_sub(int dest, int src1, int src2) + { regs[dest] = regs[src1] - regs[src2]; } - private void do_mult(int dest, int src1, int src2) { + private void do_mult(int dest, int src1, int src2) + { regs[dest] = regs[src1] * regs[src2]; } - private void do_div(int dest, int src1, int src2) { - if (regs[src2] == 0) { + private void do_div(int dest, int src1, int src2) + { + if (regs[src2] == 0){ /* no op */ - } else { + }else{ regs[dest] = regs[src1] / regs[src2]; } } private void do_load(int dest, int src, int offs) { - if (regs[src] + offs > MAX_ADDR) { + if (regs[src] + offs > MAX_ADDR){ /* no op */ - } else if (regs[src] + offs < 0) { + }else if(regs[src] + offs < 0){ /* no op */ - } else { + }else{ regs[dest] = memory[regs[src] + offs]; } } - private void do_store(int a, int offs, int b) { - if (regs[a] + offs > MAX_ADDR) { + private void do_store(int a, int offs, int b) { + if (regs[a] + offs > MAX_ADDR){ /* no op */ - } else if (regs[a] + offs < 0) { + }else if(regs[a] + offs < 0){ /* no op */ - } else { + }else{ memory[regs[a] + offs] = regs[b]; } } - private void do_move(int rd, int val) { + private void do_move(int rd, int val){ regs[rd] = val; } - private int parseReg(String s) throws InvalidInstructionException { - if (s.length() < 2) { + private int parseReg(String s) throws InvalidInstructionException + { + if (s.length() < 2){ throw new InvalidInstructionException(); } - if (s.charAt(0) != 'r') { + if (s.charAt(0) != 'r'){ throw new InvalidInstructionException(); } String numstr = s.substring(1); int num = 0; try { num = Integer.parseInt(numstr); - } catch (Exception e) { + } catch (Exception e){ throw new InvalidInstructionException(); } validate_reg(num); @@ -137,11 +124,12 @@ public class Machine { } private int parseOffset(String s) - throws InvalidInstructionException { + throws InvalidInstructionException + { int num = 0; try { num = Integer.parseInt(s); - } catch (Exception e) { + } catch (Exception e){ throw new InvalidInstructionException(); } validate_offset(num); @@ -150,37 +138,39 @@ public class Machine { private void validate_reg(int reg) - throws InvalidInstructionException { + throws InvalidInstructionException + { if (reg < 0 || reg > MAX_REG) { throw new InvalidInstructionException(); } } private void validate_offset(int offset) - throws InvalidInstructionException { + throws InvalidInstructionException + { if (offset < -MAX_ADDR || offset > MAX_ADDR) { throw new InvalidInstructionException(); } } - /** - * Execute an assembly program. + /** Execute an assembly program. * * @param prog is the program to execute as an iterable collection of strings, - * each of which is a single instruction. + * each of which is a single instruction. * @return the program's return value. * @throws Exception when program has unrecognised or - * invalid instructions, or when it returns no result when it finishes + * invalid instructions, or when it returns no result when it finishes */ int execute(List<String> instructions) throws InvalidInstructionException, - NoReturnValueException { + NoReturnValueException + { int instructionsExecuted = 0; int pc = 0; final int progLength = instructions.size(); - while (true) { - if (pc < 0 || pc >= progLength) { + while(true){ + if (pc < 0 || pc >= progLength){ /* will cause NoReturnValueException to be thrown * but that is not a bug and and indeed is what the * VM is supposed to do if the pc becomes negative, @@ -191,13 +181,13 @@ public class Machine { } String inst = instructions.get(pc); /* strip leading and trailing whitespace */ - inst = inst.toLowerCase().replaceAll("^\\s+", "").replaceAll("\\s+$", ""); + inst = inst.toLowerCase().replaceAll("^\\s+","").replaceAll("\\s+$",""); /* strip out any comments */ String[] toks = inst.split(";"); inst = toks[0]; /* check for blank lines */ - if (inst.equals("")) { + if (inst.equals("")){ pc = pc + 1; count++; continue; @@ -208,86 +198,86 @@ public class Machine { toks = inst.split("\\s+"); /* check minimum number of tokens */ - if (toks.length < 2) { + if (toks.length < 2){ throw new InvalidInstructionException(); } - if (toks[0].equals(INSTRUCTION_ADD)) { - if (toks.length != 4) { + if (toks[0].equals(INSTRUCTION_ADD)){ + if (toks.length != 4){ throw new InvalidInstructionException(); } int rd = parseReg(toks[1]); int rs1 = parseReg(toks[2]); int rs2 = parseReg(toks[3]); - do_add(rd, rs1, rs2); - } else if (toks[0].equals(INSTRUCTION_SUBTRACT)) { - if (toks.length != 4) { + do_add(rd,rs1,rs2); + } else if (toks[0].equals(INSTRUCTION_SUBTRACT)){ + if (toks.length != 4){ throw new InvalidInstructionException(); } int rd = parseReg(toks[1]); int rs1 = parseReg(toks[2]); int rs2 = parseReg(toks[3]); - do_sub(rd, rs1, rs2); - } else if (toks[0].equals(INSTRUCTION_MULT)) { - if (toks.length != 4) { + do_sub(rd,rs1,rs2); + } else if (toks[0].equals(INSTRUCTION_MULT)){ + if (toks.length != 4){ throw new InvalidInstructionException(); } int rd = parseReg(toks[1]); int rs1 = parseReg(toks[2]); int rs2 = parseReg(toks[3]); - do_mult(rd, rs1, rs2); - } else if (toks[0].equals(INSTRUCTION_DIVIDE)) { - if (toks.length != 4) { + do_mult(rd,rs1,rs2); + } else if (toks[0].equals(INSTRUCTION_DIVIDE)){ + if (toks.length != 4){ throw new InvalidInstructionException(); } int rd = parseReg(toks[1]); int rs1 = parseReg(toks[2]); int rs2 = parseReg(toks[3]); - do_div(rd, rs1, rs2); - } else if (toks[0].equals(INSTRUCTION_RETURN)) { + do_div(rd,rs1,rs2); + } else if (toks[0].equals(INSTRUCTION_RETURN)){ int rs = parseReg(toks[1]); count++; return regs[rs]; - } else if (toks[0].equals(INSTRUCTION_LOAD)) { - if (toks.length != 4) { + } else if (toks[0].equals(INSTRUCTION_LOAD)){ + if (toks.length != 4){ throw new InvalidInstructionException(); } int rd = parseReg(toks[1]); int rs = parseReg(toks[2]); int offs = parseOffset(toks[3]); - do_load(rd, rs, offs); - } else if (toks[0].equals(INSTRUCTION_STORE)) { - if (toks.length != 4) { + do_load(rd,rs,offs); + } else if (toks[0].equals(INSTRUCTION_STORE)){ + if (toks.length != 4){ throw new InvalidInstructionException(); } int ra = parseReg(toks[1]); int offs = parseOffset(toks[2]); int rb = parseReg(toks[3]); - do_store(ra, offs, rb); - } else if (toks[0].equals(INSTRUCTION_MOVE)) { - if (toks.length != 3) { + do_store(ra,offs,rb); + } else if (toks[0].equals(INSTRUCTION_MOVE)){ + if (toks.length != 3){ throw new InvalidInstructionException(); } int rd = parseReg(toks[1]); int offs = parseOffset(toks[2]); - do_move(rd, offs); - } else if (toks[0].equals(INSTRUCTION_JUMP)) { - if (toks.length != 2) { + do_move(rd,offs); + } else if (toks[0].equals(INSTRUCTION_JUMP)){ + if (toks.length != 2){ throw new InvalidInstructionException(); } int offs = parseOffset(toks[1]); - pc = pc + offs; + pc = pc + offs; count++; continue; /* avoid default increment of pc below */ - } else if (toks[0].equals(INSTRUCTION_JZ)) { - if (toks.length != 3) { + } else if (toks[0].equals(INSTRUCTION_JZ)){ + if (toks.length != 3){ throw new InvalidInstructionException(); } int ra = parseReg(toks[1]); int offs = parseOffset(toks[2]); - if (regs[ra] == 0) { + if (regs[ra] == 0){ pc = pc + offs; - } else { + }else{ pc = pc + 1; } count++; @@ -307,7 +297,7 @@ public class Machine { /** * get the number of instructions successfully executed by the VM so far */ - public int getCount() { + public int getCount(){ return count; } } diff --git a/src/swen90006/machine/SimpleDriver.java b/src/swen90006/machine/SimpleDriver.java index bf288a4d2d3262d62316a7fa8adeb2a9f9a1dd6e..c7bf13f8596efc76617f48191fb48fe45dbd6737 100644 --- a/src/swen90006/machine/SimpleDriver.java +++ b/src/swen90006/machine/SimpleDriver.java @@ -9,12 +9,12 @@ import java.util.List; public class SimpleDriver { private static final int MEMORY_SIZE = Machine.MAX_ADDR+1; - + public static void main(String[] args) throws Exception { if (args.length != 1){ System.err.println("Usage: java SimpleDriver <inputfile>"); - System.err.println("\nMust have 1 argument instead of " + args.length); + System.err.println("\nMust have 1 argument instead of " + args.length); System.exit(1); } @@ -34,7 +34,7 @@ public class SimpleDriver { System.out.println("There are this many instructions: " + lines.size()); m = new Machine(); - + Integer res = null; res = m.execute(lines); System.out.println("Program result: " + res + "\n"); diff --git a/test/swen90006/machine/BoundaryTests.java b/test/swen90006/machine/BoundaryTests.java index 946c09791cc5731207c2ccbb04e7e1ae0d3d04a5..1fc1e2c5601ce2219deef66432a791723c968a47 100644 --- a/test/swen90006/machine/BoundaryTests.java +++ b/test/swen90006/machine/BoundaryTests.java @@ -71,7 +71,7 @@ public class BoundaryTests { Machine m = new Machine(); final List<String> lines = readInstructions("./examples/B2_1.s"); int expected = m.execute(lines); - assertEquals(expected,0); + assertEquals(expected,5); }