Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

isaacy2012
Copy link

@isaacy2012 isaacy2012 commented May 20, 2023

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");
		}
	}

- Fixed an issue where SUBS instructions did not result in the correct V flag
- 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Problems with C & V flags when using the SUBS instruction
1 participant