testIntOperations method Null safety

Future<void> testIntOperations()

Implementation

Future<void> testIntOperations() async {
  await test("2's complement int operations", () async {
    Model m = newModel();
    m.wordSize = 16;
    m.displayMode = DisplayMode.decimal;
    m.integerSignMode = SignMode.twosComplement;

    // -1 + 1 = 0, set carry
    m.cFlag = false;
    m.yI = BigInt.from(-1);
    m.xI = BigInt.from(1);
    Operations16.plus.intCalc!(m);
    await expect(m.xI, BigInt.zero);
    await expect(m.cFlag, true);

    // 0 + 1 = 1, clear carry
    m.cFlag = true;
    m.yI = BigInt.from(0);
    m.xI = BigInt.from(1);
    Operations16.plus.intCalc!(m);
    await expect(m.xI, BigInt.one);
    await expect(m.cFlag, false);

    // 32767 * 2 = 32766, set overflow
    m.gFlag = false;
    m.yI = BigInt.from(32767);
    m.xI = BigInt.from(2);
    Operations16.mult.intCalc!(m);
    await expect(m.xI, BigInt.from(32766));
    await expect(m.gFlag, true);

    // 1440 / -12 = -120, clear carry
    m.cFlag = true;
    m.yI = BigInt.from(1440);
    m.xI = BigInt.from(-12);
    Operations16.div.intCalc!(m);
    await expect(m.xI, BigInt.from(-120));
    await expect(m.cFlag, false);
  });

  await test("1's complement int operations", () async {
    Model m = newModel();
    m.wordSize = 16;
    m.integerSignMode = SignMode.onesComplement;
    m.wordSize = 4;

    // -1 + -1 = -2, set carry
    m.cFlag = true;
    m.yI = BigInt.from(-1);
    m.xI = BigInt.from(-1);
    Operations16.plus.intCalc!(m);
    await expect(m.xI, BigInt.from(-2));
    await expect(m.cFlag, true);

    // 3 - 4 = -1, set borrow (that is, cFlag)
    m.cFlag = false;
    m.yI = BigInt.from(3);
    m.xI = BigInt.from(4);
    Operations16.minus.intCalc!(m);
    await expect(m.xI, BigInt.from(-1));
    await expect(m.cFlag, true);

    // -3 + 3 = 0, no carry
    m.cFlag = true;
    m.yI = BigInt.from(-3);
    m.xI = BigInt.from(3);
    Operations16.plus.intCalc!(m);
    await expect(m.xI, BigInt.from(0));
    await expect(m.cFlag, false);

    // 6 - 5 = 1, no borrow
    m.cFlag = true;
    m.yI = BigInt.from(6);
    m.xI = BigInt.from(5);
    Operations16.minus.intCalc!(m);
    await expect(m.xI, BigInt.from(1));
    await expect(m.cFlag, false);
  });

  await test("subtraction carry, 1's and 2's complement", () async {
    Model m = newModel();
    m.wordSize = 4;
    for (final c in [SignMode.onesComplement, SignMode.twosComplement]) {
      m.integerSignMode = c;

      // -6 - -4 = -2, carry set
      m.cFlag = false;
      m.yI = BigInt.from(-6);
      m.xI = BigInt.from(-4);
      Operations16.minus.intCalc!(m);
      await expect(m.xI, BigInt.from(-2));
      await expect(m.cFlag, true);

      // 6 - 1 = 5, carry cleared
      m.cFlag = true;
      m.yI = BigInt.from(6);
      m.xI = BigInt.from(1);
      Operations16.minus.intCalc!(m);
      await expect(m.xI, BigInt.from(5));
      await expect(m.cFlag, false);
    }
  });
  await test("2's complement range", () async {
    Model m = newModel();
    m.wordSize = 4;

    // 7 + 6 = -3, G set, C cleared
    m.cFlag = true;
    m.gFlag = false;
    m.yI = BigInt.from(7);
    m.xI = BigInt.from(6);
    Operations16.plus.intCalc!(m);
    await expect(m.xI, BigInt.from(-3));
    await expect(m.cFlag, false);
    await expect(m.gFlag, true);
  });

  await test('int rmd', () async {
    Model m = newModel();
    m.yI = BigInt.from(0x66);
    m.xI = BigInt.from(7);
    Operations16.div.intCalc!(m);
    await expect(m.xI, BigInt.from(0xe));
    m.pushStack();
    m.xI = BigInt.from(2);
    Operations16.div.intCalc!(m);
    await expect(m.xI, BigInt.from(0x7));
    m.pushStack();
    m.xI = BigInt.from(4);
    Operations16.rmd.intCalc!(m);
    await expect(m.xI, BigInt.from(0x3));
  });
  await test('logical operations', () async {
    // Not
    Model m = newModel();
    await expect(m.wordSize, 16); // default
    m.displayMode = DisplayMode.bin;
    m.x = m.tryParseValue('11111111')!;
    Operations16.not.intCalc!(m);
    await expect(m.x, m.tryParseValue('1111111100000000'));

    // and
    m.y = m.tryParseValue('10101')!;
    m.x = m.tryParseValue('10011')!;
    Operations16.and.intCalc!(m);
    await expect(m.x, m.tryParseValue('10001'));

    // or
    m.y = m.tryParseValue('10101')!;
    m.x = m.tryParseValue('10011')!;
    Operations16.or.intCalc!(m);
    await expect(m.x, m.tryParseValue('10111'));

    // xor
    m.y = m.tryParseValue('1010101')!;
    m.x = m.tryParseValue('1011101')!;
    Operations16.xor.intCalc!(m);
    await expect(m.x, m.tryParseValue('1000'));

    // sl (shift left)
    m.wordSize = 8;
    m.x = m.tryParseValue('10011100')!;
    Operations16.sl.intCalc!(m);
    await expect(m.x, m.tryParseValue('00111000'));
    await expect(m.cFlag, true);
    Operations16.sl.intCalc!(m);
    await expect(m.x, m.tryParseValue('01110000'));
    await expect(m.cFlag, false);

    // sr (shift right)
    Operations16.sr.intCalc!(m);
    await expect(m.x, m.tryParseValue('00111000'));
    await expect(m.cFlag, false);
    Operations16.sr.intCalc!(m);
    await expect(m.cFlag, false);
    Operations16.sr.intCalc!(m);
    await expect(m.cFlag, false);
    Operations16.sr.intCalc!(m);
    await expect(m.cFlag, false);
    Operations16.sr.intCalc!(m);
    await expect(m.x, m.tryParseValue('00000011'));
    await expect(m.cFlag, true);

    // lj (left justify)
    m.xI = BigInt.from(0);
    Operations16.lj.intCalc!(m);
    await expect(m.x, m.tryParseValue('0'));
    await expect(m.y, m.tryParseValue('0'));
    m.x = m.tryParseValue('1111')!;
    Operations16.lj.intCalc!(m);
    await expect(m.x, m.tryParseValue('100'));
    await expect(m.y, m.tryParseValue('11110000'));

    // asr
    m.integerSignMode = SignMode.unsigned;
    m.x = m.tryParseValue('10011100')!;
    Operations16.asr.intCalc!(m);
    await expect(m.x, m.tryParseValue('01001110'));
    m.integerSignMode = SignMode.twosComplement;
    m.x = m.tryParseValue('10011100')!;
    Operations16.asr.intCalc!(m);
    await expect(m.x, m.tryParseValue('11001110'));

    // rl
    m.x = m.tryParseValue('10011100')!;
    m.cFlag = false;
    Operations16.rl.intCalc!(m);
    await expect(m.cFlag, true);
    await expect(m.x, m.tryParseValue('00111001'));
    Operations16.rl.intCalc!(m);
    await expect(m.cFlag, false);
    await expect(m.x, m.tryParseValue('01110010'));

    // rr
    Operations16.rr.intCalc!(m);
    await expect(m.cFlag, false);
    await expect(m.x, m.tryParseValue('00111001'));
    Operations16.rr.intCalc!(m);
    await expect(m.cFlag, true);
    await expect(m.x, m.tryParseValue('10011100'));
    Operations16.rr.intCalc!(m);
    await expect(m.cFlag, false);
    await expect(m.x, m.tryParseValue('01001110'));

    // rlc
    m.x = m.tryParseValue('10011100')!;
    m.cFlag = false;
    Operations16.rlc.intCalc!(m);
    await expect(m.cFlag, true);
    await expect(m.x, m.tryParseValue('00111000'));
    Operations16.rlc.intCalc!(m);
    await expect(m.cFlag, false);
    await expect(m.x, m.tryParseValue('01110001'));

    // rrc
    Operations16.rrc.intCalc!(m);
    await expect(m.x, m.tryParseValue('00111000'));
    m.cFlag = true;
    Operations16.rrc.intCalc!(m);
    await expect(m.x, m.tryParseValue('10011100'));
    await expect(m.cFlag, false);
    Operations16.rrc.intCalc!(m);
    await expect(m.x, m.tryParseValue('01001110'));
    await expect(m.cFlag, false);

    // rln
    m.x = m.tryParseValue('10011100')!;
    m.pushStack();
    m.xI = BigInt.one;
    m.cFlag = false;
    Operations16.rln.intCalc!(m);
    await expect(m.cFlag, true);
    await expect(m.x, m.tryParseValue('00111001'));

    m.x = m.tryParseValue('10011100')!;
    m.pushStack();
    m.xI = BigInt.two;
    m.cFlag = true;
    Operations16.rln.intCalc!(m);
    await expect(m.cFlag, false);
    await expect(m.x, m.tryParseValue('01110010'));

    // rrn
    m.x = m.tryParseValue('01110010')!;
    m.pushStack();
    m.xI = BigInt.one;
    Operations16.rrn.intCalc!(m);
    await expect(m.cFlag, false);
    await expect(m.x, m.tryParseValue('00111001'));

    m.x = m.tryParseValue('01110010')!;
    m.pushStack();
    m.xI = BigInt.two;
    Operations16.rrn.intCalc!(m);
    await expect(m.cFlag, true);
    await expect(m.x, m.tryParseValue('10011100'));

    m.x = m.tryParseValue('01110010')!;
    m.pushStack();
    m.xI = BigInt.from(3);
    Operations16.rrn.intCalc!(m);
    await expect(m.cFlag, false);
    await expect(m.x, m.tryParseValue('01001110'));

    // rlcn
    m.x = m.tryParseValue('10011100')!;
    m.cFlag = false;
    m.pushStack();
    m.xI = BigInt.one;
    Operations16.rlcn.intCalc!(m);
    await expect(m.cFlag, true);
    await expect(m.x, m.tryParseValue('00111000'));

    m.x = m.tryParseValue('10011100')!;
    m.cFlag = false;
    m.pushStack();
    m.xI = BigInt.two;
    Operations16.rlcn.intCalc!(m);
    await expect(m.cFlag, false);
    await expect(m.x, m.tryParseValue('01110001'));

    // rrcn
    m.x = m.tryParseValue('01110001')!;
    m.cFlag = false;
    m.pushStack();
    m.xI = BigInt.one;
    Operations16.rrcn.intCalc!(m);
    await expect(m.x, m.tryParseValue('00111000'));
    await expect(m.cFlag, true);

    m.x = m.tryParseValue('01110001')!;
    m.cFlag = false;
    m.pushStack();
    m.xI = BigInt.two;
    Operations16.rrcn.intCalc!(m);
    await expect(m.x, m.tryParseValue('10011100'));
    await expect(m.cFlag, false);

    m.x = m.tryParseValue('01110001')!;
    m.cFlag = false;
    m.pushStack();
    m.xI = BigInt.from(3);
    Operations16.rrcn.intCalc!(m);
    await expect(m.x, m.tryParseValue('01001110'));
    await expect(m.cFlag, false);

    // cb
    m.y = m.tryParseValue('11111111')!;
    m.x = m.tryParseValue('00000011')!;
    Operations16.cb.intCalc!(m);
    await expect(m.x, m.tryParseValue('11110111'));

    // sb
    m.y = m.tryParseValue('01110000')!;
    m.x = m.tryParseValue('00000000')!;
    Operations16.sb.intCalc!(m);
    await expect(m.x, m.tryParseValue('01110001'));

    m.pushStack();
    m.xI = BigInt.from(7);
    Operations16.sb.intCalc!(m);
    await expect(m.x, m.tryParseValue('11110001'));

    // maskr
    m.xI = BigInt.from(4);
    Operations16.maskr.intCalc!(m);
    await expect(m.x, m.tryParseValue('00001111'));
    m.xI = BigInt.from(0);
    Operations16.maskr.intCalc!(m);
    await expect(m.x, m.tryParseValue('00000000'));
    m.xI = BigInt.from(8);
    Operations16.maskr.intCalc!(m);
    await expect(m.x, m.tryParseValue('11111111'));

    // maskl
    m.xI = BigInt.from(3);
    Operations16.maskl.intCalc!(m);
    await expect(m.x, m.tryParseValue('11100000'));
    m.xI = BigInt.from(0);
    Operations16.maskl.intCalc!(m);
    await expect(m.x, m.tryParseValue('00000000'));
    m.xI = BigInt.from(7);
    Operations16.maskl.intCalc!(m);
    await expect(m.x, m.tryParseValue('11111110'));
    m.xI = BigInt.from(8);
    Operations16.maskl.intCalc!(m);
    await expect(m.x, m.tryParseValue('11111111'));

    // #b
    m.x = m.tryParseValue('01011101')!;
    Operations16.poundB.intCalc!(m);
    await expect(m.xI, BigInt.from(5));
    m.x = m.tryParseValue('00000000')!;
    Operations16.poundB.intCalc!(m);
    await expect(m.xI, BigInt.from(0));
    m.x = m.tryParseValue('11111111')!;
    Operations16.poundB.intCalc!(m);
    await expect(m.xI, BigInt.from(8));
  });
  await test('double operations', () async {
    Model m = newModel();
    m.wordSize = 5;
    await expect(m.signMode, SignMode.twosComplement); // default
    m.displayMode = DisplayMode.bin;

    // double multiply:  7*6 = 42
    m.y = m.tryParseValue('00111')!;
    m.x = m.tryParseValue('00110')!;
    Operations16.dblx.intCalc!(m);
    await expect(m.x, m.tryParseValue('00001'));
    await expect(m.y, m.tryParseValue('01010'));

    // double divide:  -88 / 11
    m.x = m.tryParseValue('01000')!; // Z
    m.pushStack();
    m.x = m.tryParseValue('11101')!; // Y, YZ is -88
    m.pushStack();
    m.x = m.tryParseValue('01011')!; // X, 11
    Operations16.dblDiv.intCalc!(m);
    await expect(m.x, m.tryParseValue('11000'));

    // double remainder: -87 remainder 11 = -10
    m.x = m.tryParseValue('01001')!; // Z
    m.pushStack();
    m.x = m.tryParseValue('11101')!; // Y, YZ is -87
    m.pushStack();
    m.x = m.tryParseValue('01011')!; // X, 11
    Operations16.dblr.intCalc!(m);
    await expect(m.xI, BigInt.from(-10));

    // double multiply:  Unsigned f723eb313f123827 * a20175becabcde06
    //          is 9c6623a4aff98347_8e11697b49c322ea
    m.wordSize = 64;
    m.integerSignMode = SignMode.unsigned;
    m.gFlag = true;
    m.xI = BigInt.parse('f723eb313f123827', radix: 16);
    m.yI = BigInt.parse('a20175becabcde06', radix: 16);
    Operations16.dblx.intCalc!(m);
    await expect(m.xI, BigInt.parse('9c6623a4aff98347', radix: 16));
    await expect(m.yI, BigInt.parse('8e11697b49c322ea', radix: 16));
    await expect(m.gFlag, false);

    // double divide with above numbers
    m.pushStack();
    m.xI = BigInt.parse('a20175becabcde06', radix: 16);
    Operations16.dblDiv.intCalc!(m);
    await expect(m.xI, BigInt.parse('f723eb313f123827', radix: 16));

    // double remainder with big numbers
    m.xI = BigInt.parse('8e11697b49c322ec', radix: 16);
    m.pushStack();
    m.xI = BigInt.parse('9c6623a4aff98347', radix: 16);
    m.pushStack();
    m.xI = BigInt.parse('f723eb313f123827', radix: 16);
    Operations16.dblr.intCalc!(m);
    await expect(m.xI, BigInt.from(2));
  });
  await test('Unsigned add and subtract', _testUnsigned);
}