diff options
| author | Uri Shaked | 2019-11-20 22:49:18 +0200 |
|---|---|---|
| committer | Uri Shaked | 2019-11-20 22:49:18 +0200 |
| commit | e5b02ca111b5fd6fc1ff40afb0f9074c9ff26320 (patch) | |
| tree | 00ce82f5ffaf420cd5861c6710489ccb323a723d /src | |
| parent | feat: implement most instructions (diff) | |
| download | avr8js-e5b02ca111b5fd6fc1ff40afb0f9074c9ff26320.tar.gz avr8js-e5b02ca111b5fd6fc1ff40afb0f9074c9ff26320.tar.bz2 avr8js-e5b02ca111b5fd6fc1ff40afb0f9074c9ff26320.zip | |
fix: SREG issues in ADC, CPC, SBC, SBCI
also added regression test cases
Diffstat (limited to '')
| -rw-r--r-- | src/instruction.spec.ts | 47 | ||||
| -rw-r--r-- | src/instruction.ts | 15 |
2 files changed, 52 insertions, 10 deletions
diff --git a/src/instruction.spec.ts b/src/instruction.spec.ts index ccf8676..58cb33a 100644 --- a/src/instruction.spec.ts +++ b/src/instruction.spec.ts @@ -15,6 +15,30 @@ describe('avrInstruction', () => { } } + it('should execute `ADC r0, r1` instruction when carry is on', () => { + loadProgram('011c'); + cpu.data[0] = 10; // r0 <- 10 + cpu.data[1] = 20; // r1 <- 20 + cpu.data[95] = 0b00000001; // SREG <- -------C + avrInstruction(cpu); + expect(cpu.pc).toEqual(1); + expect(cpu.cycles).toEqual(1); + expect(cpu.data[0]).toEqual(31); + expect(cpu.data[95]).toEqual(0); // SREG: -------- + }); + + it('should execute `ADC r0, r1` instruction when carry is on and the result overflows', () => { + loadProgram('011c'); + cpu.data[0] = 10; // r0 <- 10 + cpu.data[1] = 245; // r1 <- 20 + cpu.data[95] = 0b00000001; // SREG <- -------C + avrInstruction(cpu); + expect(cpu.pc).toEqual(1); + expect(cpu.cycles).toEqual(1); + expect(cpu.data[0]).toEqual(0); + expect(cpu.data[95]).toEqual(0b00100011); // SREG: --H---ZC + }); + it('should execute `BCLR 2` instruction', () => { loadProgram('a894'); cpu.data[95] = 0xff; // SREG <- 0xff @@ -102,7 +126,18 @@ describe('avrInstruction', () => { avrInstruction(cpu); expect(cpu.pc).toEqual(1); expect(cpu.cycles).toEqual(1); - expect(cpu.data[95]).toEqual(0); // SREG 00000000 + expect(cpu.data[95]).toEqual(0); // SREG clear + }); + + it('should execute `CPC r24, r1` instruction and set', () => { + loadProgram('8105'); + cpu.data[1] = 0; // r1 <- 0 + cpu.data[24] = 0; // r24 <- 0 + cpu.data[95] = 0b10000001; // SREG: I-------C + avrInstruction(cpu); + expect(cpu.pc).toEqual(1); + expect(cpu.cycles).toEqual(1); + expect(cpu.data[95]).toEqual(0b10110101); // SREG: I-HS-N-C }); it('should execute `CPI r26, 0x9` instruction', () => { @@ -598,6 +633,16 @@ describe('avrInstruction', () => { expect(cpu.data[95]).toEqual(0b00011001); // SREG: SVI }); + it('should execute `SBCI r23, 3`', () => { + loadProgram('7340'); + cpu.data[23] = 3; // r23 <- 3 + cpu.data[95] = 0b10000001; // SREG <- I------C + avrInstruction(cpu); + expect(cpu.pc).toEqual(1); + expect(cpu.cycles).toEqual(1); + expect(cpu.data[95]).toEqual(0b10110101); // SREG: I-HS-N-C + }); + it('should execute `SBI 0x0c, 5`', () => { loadProgram('659a'); cpu.data[0x2c] = 0b00001111; diff --git a/src/instruction.ts b/src/instruction.ts index 30d30cc..a72218e 100644 --- a/src/instruction.ts +++ b/src/instruction.ts @@ -29,14 +29,15 @@ export function avrInstruction(cpu: ICPU) { if ((opcode & 0xfc00) === 0x1c00) { const d = cpu.data[(opcode & 0x1f0) >> 4]; const r = cpu.data[(opcode & 0xf) | ((opcode & 0x200) >> 5)]; - const R = (d + r + (cpu.data[95] & 1)) & 255; + const sum = d + r + (cpu.data[95] & 1); + const R = sum & 255; cpu.data[(opcode & 0x1f0) >> 4] = R; let sreg = cpu.data[95] & 0xc0; sreg |= R ? 0 : 2; sreg |= 128 & R ? 4 : 0; sreg |= (R ^ r) & (d ^ R) & 128 ? 8 : 0; sreg |= ((sreg >> 2) & 1) ^ ((sreg >> 3) & 1) ? 0x10 : 0; - sreg |= (d + r + (sreg & 1)) & 256 ? 1 : 0; + sreg |= sum & 256 ? 1 : 0; sreg |= 1 & ((d & r) | (r & ~R) | (~R & d)) ? 0x20 : 0; cpu.data[95] = sreg; } @@ -202,12 +203,10 @@ export function avrInstruction(cpu: ICPU) { const arg2 = cpu.data[(opcode & 0xf) | ((opcode & 0x200) >> 5)]; let sreg = cpu.data[95]; const r = arg1 - arg2 - (sreg & 1); - sreg &= 0xc0; - sreg |= 0 === r && (sreg >> 1) & 1 ? 2 : 0; + sreg = (sreg & 0xc0) | (!r && (sreg >> 1) & 1 ? 2 : 0) | (arg2 + (sreg & 1) > arg1 ? 1 : 0); sreg |= 128 & r ? 4 : 0; sreg |= (arg1 ^ arg2) & (arg1 ^ r) & 128 ? 8 : 0; sreg |= ((sreg >> 2) & 1) ^ ((sreg >> 3) & 1) ? 0x10 : 0; - sreg |= arg2 + (sreg & 1) > arg1 ? 1 : 0; sreg |= 1 & ((~arg1 & arg2) | (arg2 & r) | (r & ~arg1)) ? 0x20 : 0; cpu.data[95] = sreg; } @@ -650,11 +649,10 @@ export function avrInstruction(cpu: ICPU) { let sreg = cpu.data[95]; const R = val1 - val2 - (sreg & 1); cpu.data[(opcode & 0x1f0) >> 4] = R; - sreg = (sreg & 0xc0) | (0 === R && (sreg >> 1) & 1 ? 2 : 0); + sreg = (sreg & 0xc0) | (!R && (sreg >> 1) & 1 ? 2 : 0) | (val2 + (sreg & 1) > val1 ? 1 : 0); sreg |= 128 & R ? 4 : 0; sreg |= (val1 ^ val2) & (val1 ^ R) & 128 ? 8 : 0; sreg |= ((sreg >> 2) & 1) ^ ((sreg >> 3) & 1) ? 0x10 : 0; - sreg |= val2 + (sreg & 1) > val1 ? 1 : 0; sreg |= 1 & ((~val1 & val2) | (val2 & R) | (R & ~val1)) ? 0x20 : 0; cpu.data[95] = sreg; } @@ -666,11 +664,10 @@ export function avrInstruction(cpu: ICPU) { let sreg = cpu.data[95]; const R = val1 - val2 - (sreg & 1); cpu.data[((opcode & 0xf0) >> 4) + 16] = R; - sreg = (sreg & 0xc0) | (0 === R && (sreg >> 1) & 1 ? 2 : 0); + sreg = (sreg & 0xc0) | (!R && (sreg >> 1) & 1 ? 2 : 0) | (val2 + (sreg & 1) > val1 ? 1 : 0); sreg |= 128 & R ? 4 : 0; sreg |= (val1 ^ val2) & (val1 ^ R) & 128 ? 8 : 0; sreg |= ((sreg >> 2) & 1) ^ ((sreg >> 3) & 1) ? 0x10 : 0; - sreg |= val2 + (sreg & 1) > val1 ? 1 : 0; sreg |= 1 & ((~val1 & val2) | (val2 & R) | (R & ~val1)) ? 0x20 : 0; cpu.data[95] = sreg; } |
