diff options
Diffstat (limited to '')
| -rw-r--r-- | src/cpu/instruction.spec.ts | 28 | ||||
| -rw-r--r-- | src/cpu/instruction.ts | 25 |
2 files changed, 33 insertions, 20 deletions
diff --git a/src/cpu/instruction.spec.ts b/src/cpu/instruction.spec.ts index 5ad160d..2312f6c 100644 --- a/src/cpu/instruction.spec.ts +++ b/src/cpu/instruction.spec.ts @@ -395,7 +395,7 @@ describe('avrInstruction', () => { cpu.data[26] = 0xc0; // X <- 0xc0 avrInstruction(cpu); expect(cpu.pc).toEqual(1); - expect(cpu.cycles).toEqual(1); + expect(cpu.cycles).toEqual(2); expect(cpu.data[1]).toEqual(0x15); expect(cpu.data[26]).toEqual(0xc0); // verify that X was unchanged }); @@ -417,7 +417,7 @@ describe('avrInstruction', () => { cpu.data[26] = 0x99; // X <- 0x99 avrInstruction(cpu); expect(cpu.pc).toEqual(1); - expect(cpu.cycles).toEqual(3); + expect(cpu.cycles).toEqual(2); expect(cpu.data[1]).toEqual(0x22); expect(cpu.data[26]).toEqual(0x98); // verify that X was decremented }); @@ -428,7 +428,7 @@ describe('avrInstruction', () => { cpu.data[28] = 0xc0; // Y <- 0xc0 avrInstruction(cpu); expect(cpu.pc).toEqual(1); - expect(cpu.cycles).toEqual(1); + expect(cpu.cycles).toEqual(2); expect(cpu.data[8]).toEqual(0x15); expect(cpu.data[28]).toEqual(0xc0); // verify that Y was unchanged }); @@ -450,7 +450,7 @@ describe('avrInstruction', () => { cpu.data[28] = 0x99; // Y <- 0x99 avrInstruction(cpu); expect(cpu.pc).toEqual(1); - expect(cpu.cycles).toEqual(3); + expect(cpu.cycles).toEqual(2); expect(cpu.data[0]).toEqual(0x22); expect(cpu.data[28]).toEqual(0x98); // verify that Y was decremented }); @@ -461,7 +461,7 @@ describe('avrInstruction', () => { cpu.data[28] = 0x80; // Y <- 0x80 avrInstruction(cpu); expect(cpu.pc).toEqual(1); - expect(cpu.cycles).toEqual(3); + expect(cpu.cycles).toEqual(2); expect(cpu.data[4]).toEqual(0x33); expect(cpu.data[28]).toEqual(0x80); // verify that Y was unchanged }); @@ -472,7 +472,7 @@ describe('avrInstruction', () => { cpu.data[30] = 0xcc; // Z <- 0xcc avrInstruction(cpu); expect(cpu.pc).toEqual(1); - expect(cpu.cycles).toEqual(1); + expect(cpu.cycles).toEqual(2); expect(cpu.data[5]).toEqual(0xf5); expect(cpu.data[30]).toEqual(0xcc); // verify that Z was unchanged }); @@ -494,7 +494,7 @@ describe('avrInstruction', () => { cpu.data[30] = 0x9f; // Z <- 0x9f avrInstruction(cpu); expect(cpu.pc).toEqual(1); - expect(cpu.cycles).toEqual(3); + expect(cpu.cycles).toEqual(2); expect(cpu.data[0]).toEqual(0x66); expect(cpu.data[30]).toEqual(0x9e); // verify that Y was decremented }); @@ -505,7 +505,7 @@ describe('avrInstruction', () => { cpu.data[30] = 0x80; // Z <- 0x80 avrInstruction(cpu); expect(cpu.pc).toEqual(1); - expect(cpu.cycles).toEqual(3); + expect(cpu.cycles).toEqual(2); expect(cpu.data[15]).toEqual(0x33); expect(cpu.data[30]).toEqual(0x80); // verify that Z was unchanged }); @@ -839,7 +839,7 @@ describe('avrInstruction', () => { cpu.data[26] = 0x9a; // X <- 0x9a avrInstruction(cpu); expect(cpu.pc).toEqual(1); - expect(cpu.cycles).toEqual(1); + expect(cpu.cycles).toEqual(2); expect(cpu.data[0x9a]).toEqual(0x5a); expect(cpu.data[26]).toEqual(0x9a); // verify that X was unchanged }); @@ -850,7 +850,7 @@ describe('avrInstruction', () => { cpu.data[26] = 0x9a; // X <- 0x9a avrInstruction(cpu); expect(cpu.pc).toEqual(1); - expect(cpu.cycles).toEqual(1); + expect(cpu.cycles).toEqual(2); expect(cpu.data[0x9a]).toEqual(0x5a); expect(cpu.data[26]).toEqual(0x9b); // verify that X was incremented }); @@ -872,7 +872,7 @@ describe('avrInstruction', () => { cpu.data[28] = 0x9a; // Y <- 0x9a avrInstruction(cpu); expect(cpu.pc).toEqual(1); - expect(cpu.cycles).toEqual(1); + expect(cpu.cycles).toEqual(2); expect(cpu.data[0x9a]).toEqual(0x5b); expect(cpu.data[28]).toEqual(0x9a); // verify that Y was unchanged }); @@ -883,7 +883,7 @@ describe('avrInstruction', () => { cpu.data[28] = 0x9a; // Y <- 0x9a avrInstruction(cpu); expect(cpu.pc).toEqual(1); - expect(cpu.cycles).toEqual(1); + expect(cpu.cycles).toEqual(2); expect(cpu.data[0x9a]).toEqual(0x5a); expect(cpu.data[28]).toEqual(0x9b); // verify that Y was incremented }); @@ -916,7 +916,7 @@ describe('avrInstruction', () => { cpu.data[30] = 0x40; // Z <- 0x40 avrInstruction(cpu); expect(cpu.pc).toEqual(1); - expect(cpu.cycles).toEqual(1); + expect(cpu.cycles).toEqual(2); expect(cpu.data[0x40]).toEqual(0xdf); expect(cpu.data[30]).toEqual(0x40); // verify that Z was unchanged }); @@ -927,7 +927,7 @@ describe('avrInstruction', () => { cpu.dataView.setUint16(30, 0x155, true); // Z <- 0x155 avrInstruction(cpu); expect(cpu.pc).toEqual(1); - expect(cpu.cycles).toEqual(1); + expect(cpu.cycles).toEqual(2); expect(cpu.data[0x155]).toEqual(0x55); expect(cpu.dataView.getUint16(30, true)).toEqual(0x156); // verify that Z was incremented }); diff --git a/src/cpu/instruction.ts b/src/cpu/instruction.ts index 40ff71f..223a320 100644 --- a/src/cpu/instruction.ts +++ b/src/cpu/instruction.ts @@ -1,9 +1,13 @@ /** * AVR-8 Instruction Simulation * Part of AVR8js + * * Reference: http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf * - * Copyright (C) 2019, Uri Shaked + * Instruction timing is currently based on ATmega328p (see the Instruction Set Summary at the end of + * the datasheet) + * + * Copyright (C) 2019, 2020 Uri Shaked */ import { ICPU } from './cpu'; @@ -350,6 +354,7 @@ export function avrInstruction(cpu: ICPU) { } else if ((opcode & 0xfe0f) === 0x900c) { /* LDX, 1001 000d dddd 1100 */ cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(cpu.dataView.getUint16(26, true)); + cpu.cycles++; } else if ((opcode & 0xfe0f) === 0x900d) { /* LDX(INC), 1001 000d dddd 1101 */ const x = cpu.dataView.getUint16(26, true); @@ -361,10 +366,11 @@ export function avrInstruction(cpu: ICPU) { const x = cpu.dataView.getUint16(26, true) - 1; cpu.dataView.setUint16(26, x, true); cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(x); - cpu.cycles += 2; + cpu.cycles++; } else if ((opcode & 0xfe0f) === 0x8008) { /* LDY, 1000 000d dddd 1000 */ cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(cpu.dataView.getUint16(28, true)); + cpu.cycles++; } else if ((opcode & 0xfe0f) === 0x9009) { /* LDY(INC), 1001 000d dddd 1001 */ const y = cpu.dataView.getUint16(28, true); @@ -376,7 +382,7 @@ export function avrInstruction(cpu: ICPU) { const y = cpu.dataView.getUint16(28, true) - 1; cpu.dataView.setUint16(28, y, true); cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(y); - cpu.cycles += 2; + cpu.cycles++; } else if ( (opcode & 0xd208) === 0x8008 && (opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8) @@ -386,10 +392,11 @@ export function avrInstruction(cpu: ICPU) { cpu.dataView.getUint16(28, true) + ((opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8)) ); - cpu.cycles += 2; + cpu.cycles++; } else if ((opcode & 0xfe0f) === 0x8000) { /* LDZ, 1000 000d dddd 0000 */ cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(cpu.dataView.getUint16(30, true)); + cpu.cycles++; } else if ((opcode & 0xfe0f) === 0x9001) { /* LDZ(INC), 1001 000d dddd 0001 */ const z = cpu.dataView.getUint16(30, true); @@ -401,7 +408,7 @@ export function avrInstruction(cpu: ICPU) { const z = cpu.dataView.getUint16(30, true) - 1; cpu.dataView.setUint16(30, z, true); cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(z); - cpu.cycles += 2; + cpu.cycles++; } else if ( (opcode & 0xd208) === 0x8000 && (opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8) @@ -411,7 +418,7 @@ export function avrInstruction(cpu: ICPU) { cpu.dataView.getUint16(30, true) + ((opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8)) ); - cpu.cycles += 2; + cpu.cycles++; } else if (opcode === 0x95c8) { /* LPM, 1001 0101 1100 1000 */ cpu.data[0] = cpu.progBytes[cpu.dataView.getUint16(30, true)]; @@ -666,11 +673,13 @@ export function avrInstruction(cpu: ICPU) { } else if ((opcode & 0xfe0f) === 0x920c) { /* STX, 1001 001r rrrr 1100 */ cpu.writeData(cpu.dataView.getUint16(26, true), cpu.data[(opcode & 0x1f0) >> 4]); + cpu.cycles++; } else if ((opcode & 0xfe0f) === 0x920d) { /* STX(INC), 1001 001r rrrr 1101 */ const x = cpu.dataView.getUint16(26, true); cpu.writeData(x, cpu.data[(opcode & 0x1f0) >> 4]); cpu.dataView.setUint16(26, x + 1, true); + cpu.cycles++; } else if ((opcode & 0xfe0f) === 0x920e) { /* STX(DEC), 1001 001r rrrr 1110 */ const i = cpu.data[(opcode & 0x1f0) >> 4]; @@ -681,12 +690,14 @@ export function avrInstruction(cpu: ICPU) { } else if ((opcode & 0xfe0f) === 0x8208) { /* STY, 1000 001r rrrr 1000 */ cpu.writeData(cpu.dataView.getUint16(28, true), cpu.data[(opcode & 0x1f0) >> 4]); + cpu.cycles++; } else if ((opcode & 0xfe0f) === 0x9209) { /* STY(INC), 1001 001r rrrr 1001 */ const i = cpu.data[(opcode & 0x1f0) >> 4]; const y = cpu.dataView.getUint16(28, true); cpu.writeData(y, i); cpu.dataView.setUint16(28, y + 1, true); + cpu.cycles++; } else if ((opcode & 0xfe0f) === 0x920a) { /* STY(DEC), 1001 001r rrrr 1010 */ const i = cpu.data[(opcode & 0x1f0) >> 4]; @@ -708,11 +719,13 @@ export function avrInstruction(cpu: ICPU) { } else if ((opcode & 0xfe0f) === 0x8200) { /* STZ, 1000 001r rrrr 0000 */ cpu.writeData(cpu.dataView.getUint16(30, true), cpu.data[(opcode & 0x1f0) >> 4]); + cpu.cycles++; } else if ((opcode & 0xfe0f) === 0x9201) { /* STZ(INC), 1001 001r rrrr 0001 */ const z = cpu.dataView.getUint16(30, true); cpu.writeData(z, cpu.data[(opcode & 0x1f0) >> 4]); cpu.dataView.setUint16(30, z + 1, true); + cpu.cycles++; } else if ((opcode & 0xfe0f) === 0x9202) { /* STZ(DEC), 1001 001r rrrr 0010 */ const i = cpu.data[(opcode & 0x1f0) >> 4]; |
