Graphical-Micro-Architecture-Simulator icon indicating copy to clipboard operation
Graphical-Micro-Architecture-Simulator copied to clipboard

Fix issues relating to setting flags on ADDS and SUBS instructions:

Open isaacy2012 opened this issue 2 years ago • 0 comments

Fixes #4

  1. Fixed an issue where SUBS instructions did not result in the correct V flag
  2. Fixed an issue where ADDS and SUBS instructions did not result in the correct condition flags when the destination register was one of the operand registers

To fix 1

setVflag(long result, long op1, long op2) is split into setVflagAdd and setVflagSub variants, and the V flag is set based on the table "Overflow conditions for addition and subtraction." in p.190 of the Computer Organization and Design (Arm Edition) textbook.

To fix 2

the ADDSetFlags and SUBSetFlags are called before the register value is changed.

Building & Testing

I was unable to build the project, and could not find existing tests, so I tested with a simple main script in CPU.java (not committed but attached here for reference).

Since I cannot build the project, the packaged web app is unchanged. I was able to download the gws dependency but not the ace one, it would be good to get instructions on how to build the project if possible.

	public static void main(String[] args) {
		test_positive_plus_positive_is_negative_vflag_true();
		test_positive_plus_positive_is_positive_vflag_false();
		test_negative_plus_negative_is_negative_vflag_false();
		test_negative_plus_negative_is_positive_vflag_true();

		test_positive_minus_negative_is_negative_vflag_true();
		test_positive_minus_negative_is_positive_vflag_false();
		test_negative_minus_positive_is_positive_vflag_true();
		test_negative_minus_positive_is_negative_vflag_false();

		test_positive_plus_positive_is_negative_vflag_true_when_same_dest();
		test_positive_minus_negative_is_negative_vflag_true_when_same_dest();
	}

	/**
	 * positive + positive = positive --> v == true
	 */
	private static void test_positive_plus_positive_is_positive_vflag_false() {
		CPU cpu = new CPU();
		cpu.registerFile[X1] = Long.MAX_VALUE - 1;
		cpu.ORRI(X2, XZR, 1);
		cpu.ADDS(X5, X1, X2);
		assertFalse(cpu.getVflag());
	}

	/**
	 * positive + positive = negative --> v == true
	 */
	private static void test_positive_plus_positive_is_negative_vflag_true() {
		CPU cpu = new CPU();
		cpu.registerFile[X1] = Long.MAX_VALUE - 1;
		cpu.ORRI(X2, XZR, 2);
		cpu.ADDS(X5, X1, X2);
		assertTrue(cpu.getVflag());
	}

	/**
	 * positive + positive = negative --> v == true
	 * FAILS!
	 */
	private static void test_positive_plus_positive_is_negative_vflag_true_when_same_dest() {
		CPU cpu = new CPU();
		cpu.registerFile[X1] = Long.MAX_VALUE - 1;
		cpu.ORRI(X2, XZR, 2);
		cpu.ADDS(X1, X1, X2);
		assertTrue(cpu.getVflag());
	}

	/**
	 * negative + negative = negative --> v == false
	 */
	private static void test_negative_plus_negative_is_negative_vflag_false() {
		CPU cpu = new CPU();
		cpu.registerFile[X1] = Long.MIN_VALUE + 1;
		cpu.ORRI(X2, XZR, -1);
		cpu.ADDS(X5, X1, X2);
		assertFalse(cpu.getVflag());
	}

	/**
	 * negative + negative = positive --> v == true
	 */
	private static void test_negative_plus_negative_is_positive_vflag_true() {
		CPU cpu = new CPU();
		cpu.registerFile[X1] = Long.MIN_VALUE + 1;
		cpu.ORRI(X2, XZR, -2);
		cpu.ADDS(X5, X1, X2);
		assertTrue(cpu.getVflag());
	}

	/**
	 * positive - negative = negative --> v == true
	 * FAILS!
 	 */
	private static void test_positive_minus_negative_is_negative_vflag_true() {
		CPU cpu = new CPU();
		cpu.registerFile[X1] = Long.MAX_VALUE - 1;
		cpu.ORRI(X2, XZR, -2);
		cpu.SUBS(X5, X1, X2);
		assertTrue(cpu.getVflag());
	}

	/**
	 * positive - negative = negative --> v == true
	 * FAILS!
	 */
	private static void test_positive_minus_negative_is_negative_vflag_true_when_same_dest() {
		CPU cpu = new CPU();
		cpu.registerFile[X1] = Long.MAX_VALUE - 1;
		cpu.ORRI(X2, XZR, -2);
		cpu.SUBS(X1, X1, X2);
		assertTrue(cpu.getVflag());
	}

	/**
	 * positive - negative = positive --> v == true
	 */
	private static void test_positive_minus_negative_is_positive_vflag_false() {
		CPU cpu = new CPU();
		cpu.registerFile[X1] = Long.MAX_VALUE - 1;
		cpu.ORRI(X2, XZR, -1);
		cpu.SUBS(X5, X1, X2);
		assertFalse(cpu.getVflag());
	}

	/**
	 * negative - positive = positive --> v == true
	 */
	private static void test_negative_minus_positive_is_positive_vflag_true() {
		CPU cpu = new CPU();
		cpu.registerFile[X1] = Long.MAX_VALUE - 1;
		cpu.ORRI(X2, XZR, 2);
		cpu.SUBS(X5, X1, X2);
		assertFalse(cpu.getVflag());
	}

	/**
	 * negative - positive = negative --> v == false
	 */
	private static void test_negative_minus_positive_is_negative_vflag_false() {
		CPU cpu = new CPU();
		cpu.registerFile[X1] = Long.MAX_VALUE - 1;
		cpu.ORRI(X2, XZR, 2);
		cpu.SUBS(X5, X1, X2);
		assertFalse(cpu.getVflag());
	}

	private static void assertTrue(boolean b) {
		if (!b) {
			throw new RuntimeException("Fail");
		}
	}

	private static void assertFalse(boolean b) {
		if (b) {
			throw new RuntimeException("Fail");
		}
	}

isaacy2012 avatar May 20 '23 14:05 isaacy2012