Skip to content

Commit b8c08a1

Browse files
committed
fix(instruction): LD, ST instructions should take 2 clock cycles
close #39
1 parent 38bc09b commit b8c08a1

File tree

2 files changed

+33
-20
lines changed

2 files changed

+33
-20
lines changed

src/cpu/instruction.spec.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ describe('avrInstruction', () => {
395395
cpu.data[26] = 0xc0; // X <- 0xc0
396396
avrInstruction(cpu);
397397
expect(cpu.pc).toEqual(1);
398-
expect(cpu.cycles).toEqual(1);
398+
expect(cpu.cycles).toEqual(2);
399399
expect(cpu.data[1]).toEqual(0x15);
400400
expect(cpu.data[26]).toEqual(0xc0); // verify that X was unchanged
401401
});
@@ -417,7 +417,7 @@ describe('avrInstruction', () => {
417417
cpu.data[26] = 0x99; // X <- 0x99
418418
avrInstruction(cpu);
419419
expect(cpu.pc).toEqual(1);
420-
expect(cpu.cycles).toEqual(3);
420+
expect(cpu.cycles).toEqual(2);
421421
expect(cpu.data[1]).toEqual(0x22);
422422
expect(cpu.data[26]).toEqual(0x98); // verify that X was decremented
423423
});
@@ -428,7 +428,7 @@ describe('avrInstruction', () => {
428428
cpu.data[28] = 0xc0; // Y <- 0xc0
429429
avrInstruction(cpu);
430430
expect(cpu.pc).toEqual(1);
431-
expect(cpu.cycles).toEqual(1);
431+
expect(cpu.cycles).toEqual(2);
432432
expect(cpu.data[8]).toEqual(0x15);
433433
expect(cpu.data[28]).toEqual(0xc0); // verify that Y was unchanged
434434
});
@@ -450,7 +450,7 @@ describe('avrInstruction', () => {
450450
cpu.data[28] = 0x99; // Y <- 0x99
451451
avrInstruction(cpu);
452452
expect(cpu.pc).toEqual(1);
453-
expect(cpu.cycles).toEqual(3);
453+
expect(cpu.cycles).toEqual(2);
454454
expect(cpu.data[0]).toEqual(0x22);
455455
expect(cpu.data[28]).toEqual(0x98); // verify that Y was decremented
456456
});
@@ -461,7 +461,7 @@ describe('avrInstruction', () => {
461461
cpu.data[28] = 0x80; // Y <- 0x80
462462
avrInstruction(cpu);
463463
expect(cpu.pc).toEqual(1);
464-
expect(cpu.cycles).toEqual(3);
464+
expect(cpu.cycles).toEqual(2);
465465
expect(cpu.data[4]).toEqual(0x33);
466466
expect(cpu.data[28]).toEqual(0x80); // verify that Y was unchanged
467467
});
@@ -472,7 +472,7 @@ describe('avrInstruction', () => {
472472
cpu.data[30] = 0xcc; // Z <- 0xcc
473473
avrInstruction(cpu);
474474
expect(cpu.pc).toEqual(1);
475-
expect(cpu.cycles).toEqual(1);
475+
expect(cpu.cycles).toEqual(2);
476476
expect(cpu.data[5]).toEqual(0xf5);
477477
expect(cpu.data[30]).toEqual(0xcc); // verify that Z was unchanged
478478
});
@@ -494,7 +494,7 @@ describe('avrInstruction', () => {
494494
cpu.data[30] = 0x9f; // Z <- 0x9f
495495
avrInstruction(cpu);
496496
expect(cpu.pc).toEqual(1);
497-
expect(cpu.cycles).toEqual(3);
497+
expect(cpu.cycles).toEqual(2);
498498
expect(cpu.data[0]).toEqual(0x66);
499499
expect(cpu.data[30]).toEqual(0x9e); // verify that Y was decremented
500500
});
@@ -505,7 +505,7 @@ describe('avrInstruction', () => {
505505
cpu.data[30] = 0x80; // Z <- 0x80
506506
avrInstruction(cpu);
507507
expect(cpu.pc).toEqual(1);
508-
expect(cpu.cycles).toEqual(3);
508+
expect(cpu.cycles).toEqual(2);
509509
expect(cpu.data[15]).toEqual(0x33);
510510
expect(cpu.data[30]).toEqual(0x80); // verify that Z was unchanged
511511
});
@@ -839,7 +839,7 @@ describe('avrInstruction', () => {
839839
cpu.data[26] = 0x9a; // X <- 0x9a
840840
avrInstruction(cpu);
841841
expect(cpu.pc).toEqual(1);
842-
expect(cpu.cycles).toEqual(1);
842+
expect(cpu.cycles).toEqual(2);
843843
expect(cpu.data[0x9a]).toEqual(0x5a);
844844
expect(cpu.data[26]).toEqual(0x9a); // verify that X was unchanged
845845
});
@@ -850,7 +850,7 @@ describe('avrInstruction', () => {
850850
cpu.data[26] = 0x9a; // X <- 0x9a
851851
avrInstruction(cpu);
852852
expect(cpu.pc).toEqual(1);
853-
expect(cpu.cycles).toEqual(1);
853+
expect(cpu.cycles).toEqual(2);
854854
expect(cpu.data[0x9a]).toEqual(0x5a);
855855
expect(cpu.data[26]).toEqual(0x9b); // verify that X was incremented
856856
});
@@ -872,7 +872,7 @@ describe('avrInstruction', () => {
872872
cpu.data[28] = 0x9a; // Y <- 0x9a
873873
avrInstruction(cpu);
874874
expect(cpu.pc).toEqual(1);
875-
expect(cpu.cycles).toEqual(1);
875+
expect(cpu.cycles).toEqual(2);
876876
expect(cpu.data[0x9a]).toEqual(0x5b);
877877
expect(cpu.data[28]).toEqual(0x9a); // verify that Y was unchanged
878878
});
@@ -883,7 +883,7 @@ describe('avrInstruction', () => {
883883
cpu.data[28] = 0x9a; // Y <- 0x9a
884884
avrInstruction(cpu);
885885
expect(cpu.pc).toEqual(1);
886-
expect(cpu.cycles).toEqual(1);
886+
expect(cpu.cycles).toEqual(2);
887887
expect(cpu.data[0x9a]).toEqual(0x5a);
888888
expect(cpu.data[28]).toEqual(0x9b); // verify that Y was incremented
889889
});
@@ -916,7 +916,7 @@ describe('avrInstruction', () => {
916916
cpu.data[30] = 0x40; // Z <- 0x40
917917
avrInstruction(cpu);
918918
expect(cpu.pc).toEqual(1);
919-
expect(cpu.cycles).toEqual(1);
919+
expect(cpu.cycles).toEqual(2);
920920
expect(cpu.data[0x40]).toEqual(0xdf);
921921
expect(cpu.data[30]).toEqual(0x40); // verify that Z was unchanged
922922
});
@@ -927,7 +927,7 @@ describe('avrInstruction', () => {
927927
cpu.dataView.setUint16(30, 0x155, true); // Z <- 0x155
928928
avrInstruction(cpu);
929929
expect(cpu.pc).toEqual(1);
930-
expect(cpu.cycles).toEqual(1);
930+
expect(cpu.cycles).toEqual(2);
931931
expect(cpu.data[0x155]).toEqual(0x55);
932932
expect(cpu.dataView.getUint16(30, true)).toEqual(0x156); // verify that Z was incremented
933933
});

src/cpu/instruction.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
/**
22
* AVR-8 Instruction Simulation
33
* Part of AVR8js
4+
*
45
* Reference: http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf
56
*
6-
* Copyright (C) 2019, Uri Shaked
7+
* Instruction timing is currently based on ATmega328p (see the Instruction Set Summary at the end of
8+
* the datasheet)
9+
*
10+
* Copyright (C) 2019, 2020 Uri Shaked
711
*/
812

913
import { ICPU } from './cpu';
@@ -350,6 +354,7 @@ export function avrInstruction(cpu: ICPU) {
350354
} else if ((opcode & 0xfe0f) === 0x900c) {
351355
/* LDX, 1001 000d dddd 1100 */
352356
cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(cpu.dataView.getUint16(26, true));
357+
cpu.cycles++;
353358
} else if ((opcode & 0xfe0f) === 0x900d) {
354359
/* LDX(INC), 1001 000d dddd 1101 */
355360
const x = cpu.dataView.getUint16(26, true);
@@ -361,10 +366,11 @@ export function avrInstruction(cpu: ICPU) {
361366
const x = cpu.dataView.getUint16(26, true) - 1;
362367
cpu.dataView.setUint16(26, x, true);
363368
cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(x);
364-
cpu.cycles += 2;
369+
cpu.cycles++;
365370
} else if ((opcode & 0xfe0f) === 0x8008) {
366371
/* LDY, 1000 000d dddd 1000 */
367372
cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(cpu.dataView.getUint16(28, true));
373+
cpu.cycles++;
368374
} else if ((opcode & 0xfe0f) === 0x9009) {
369375
/* LDY(INC), 1001 000d dddd 1001 */
370376
const y = cpu.dataView.getUint16(28, true);
@@ -376,7 +382,7 @@ export function avrInstruction(cpu: ICPU) {
376382
const y = cpu.dataView.getUint16(28, true) - 1;
377383
cpu.dataView.setUint16(28, y, true);
378384
cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(y);
379-
cpu.cycles += 2;
385+
cpu.cycles++;
380386
} else if (
381387
(opcode & 0xd208) === 0x8008 &&
382388
(opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8)
@@ -386,10 +392,11 @@ export function avrInstruction(cpu: ICPU) {
386392
cpu.dataView.getUint16(28, true) +
387393
((opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8))
388394
);
389-
cpu.cycles += 2;
395+
cpu.cycles++;
390396
} else if ((opcode & 0xfe0f) === 0x8000) {
391397
/* LDZ, 1000 000d dddd 0000 */
392398
cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(cpu.dataView.getUint16(30, true));
399+
cpu.cycles++;
393400
} else if ((opcode & 0xfe0f) === 0x9001) {
394401
/* LDZ(INC), 1001 000d dddd 0001 */
395402
const z = cpu.dataView.getUint16(30, true);
@@ -401,7 +408,7 @@ export function avrInstruction(cpu: ICPU) {
401408
const z = cpu.dataView.getUint16(30, true) - 1;
402409
cpu.dataView.setUint16(30, z, true);
403410
cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(z);
404-
cpu.cycles += 2;
411+
cpu.cycles++;
405412
} else if (
406413
(opcode & 0xd208) === 0x8000 &&
407414
(opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8)
@@ -411,7 +418,7 @@ export function avrInstruction(cpu: ICPU) {
411418
cpu.dataView.getUint16(30, true) +
412419
((opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8))
413420
);
414-
cpu.cycles += 2;
421+
cpu.cycles++;
415422
} else if (opcode === 0x95c8) {
416423
/* LPM, 1001 0101 1100 1000 */
417424
cpu.data[0] = cpu.progBytes[cpu.dataView.getUint16(30, true)];
@@ -666,11 +673,13 @@ export function avrInstruction(cpu: ICPU) {
666673
} else if ((opcode & 0xfe0f) === 0x920c) {
667674
/* STX, 1001 001r rrrr 1100 */
668675
cpu.writeData(cpu.dataView.getUint16(26, true), cpu.data[(opcode & 0x1f0) >> 4]);
676+
cpu.cycles++;
669677
} else if ((opcode & 0xfe0f) === 0x920d) {
670678
/* STX(INC), 1001 001r rrrr 1101 */
671679
const x = cpu.dataView.getUint16(26, true);
672680
cpu.writeData(x, cpu.data[(opcode & 0x1f0) >> 4]);
673681
cpu.dataView.setUint16(26, x + 1, true);
682+
cpu.cycles++;
674683
} else if ((opcode & 0xfe0f) === 0x920e) {
675684
/* STX(DEC), 1001 001r rrrr 1110 */
676685
const i = cpu.data[(opcode & 0x1f0) >> 4];
@@ -681,12 +690,14 @@ export function avrInstruction(cpu: ICPU) {
681690
} else if ((opcode & 0xfe0f) === 0x8208) {
682691
/* STY, 1000 001r rrrr 1000 */
683692
cpu.writeData(cpu.dataView.getUint16(28, true), cpu.data[(opcode & 0x1f0) >> 4]);
693+
cpu.cycles++;
684694
} else if ((opcode & 0xfe0f) === 0x9209) {
685695
/* STY(INC), 1001 001r rrrr 1001 */
686696
const i = cpu.data[(opcode & 0x1f0) >> 4];
687697
const y = cpu.dataView.getUint16(28, true);
688698
cpu.writeData(y, i);
689699
cpu.dataView.setUint16(28, y + 1, true);
700+
cpu.cycles++;
690701
} else if ((opcode & 0xfe0f) === 0x920a) {
691702
/* STY(DEC), 1001 001r rrrr 1010 */
692703
const i = cpu.data[(opcode & 0x1f0) >> 4];
@@ -708,11 +719,13 @@ export function avrInstruction(cpu: ICPU) {
708719
} else if ((opcode & 0xfe0f) === 0x8200) {
709720
/* STZ, 1000 001r rrrr 0000 */
710721
cpu.writeData(cpu.dataView.getUint16(30, true), cpu.data[(opcode & 0x1f0) >> 4]);
722+
cpu.cycles++;
711723
} else if ((opcode & 0xfe0f) === 0x9201) {
712724
/* STZ(INC), 1001 001r rrrr 0001 */
713725
const z = cpu.dataView.getUint16(30, true);
714726
cpu.writeData(z, cpu.data[(opcode & 0x1f0) >> 4]);
715727
cpu.dataView.setUint16(30, z + 1, true);
728+
cpu.cycles++;
716729
} else if ((opcode & 0xfe0f) === 0x9202) {
717730
/* STZ(DEC), 1001 001r rrrr 0010 */
718731
const i = cpu.data[(opcode & 0x1f0) >> 4];

0 commit comments

Comments
 (0)