aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUri Shaked2019-11-19 22:26:56 +0200
committerUri Shaked2019-11-19 22:26:56 +0200
commitc0690542de387ddbd25111312220d324979c9c5c (patch)
tree9a6df961de7aff63d6aec5d6d9e38b6ecb1f08c8
parentfeat: STY/STZ/STDY/STDZ instructions + tests (diff)
downloadavr8js-c0690542de387ddbd25111312220d324979c9c5c.tar.gz
avr8js-c0690542de387ddbd25111312220d324979c9c5c.tar.bz2
avr8js-c0690542de387ddbd25111312220d324979c9c5c.zip
feat: LDY/LDZ/LDDY/LDDZ instructions + tests
-rw-r--r--src/instruction.spec.ts102
-rw-r--r--src/instruction.ts62
2 files changed, 142 insertions, 22 deletions
diff --git a/src/instruction.spec.ts b/src/instruction.spec.ts
index f804a85..29c9a49 100644
--- a/src/instruction.spec.ts
+++ b/src/instruction.spec.ts
@@ -72,11 +72,11 @@ describe('avrInstruction', () => {
it('should execute `LD r17, X+` instruction', () => {
loadProgram('1d91');
cpu.data[0xc0] = 0x15;
- cpu.data[26] = 0xc0; // X <- 0x9a
+ cpu.data[26] = 0xc0; // X <- 0xc0
avrInstruction(cpu);
expect(cpu.pc).toEqual(1);
expect(cpu.cycles).toEqual(2);
- expect(cpu.data[0xc0]).toEqual(0x15);
+ expect(cpu.data[17]).toEqual(0x15);
expect(cpu.data[26]).toEqual(0xc1); // verify that X was incremented
});
@@ -91,6 +91,94 @@ describe('avrInstruction', () => {
expect(cpu.data[26]).toEqual(0x98); // verify that X was decremented
});
+ it('should execute `LD r8, Y` instruction', () => {
+ loadProgram('8880');
+ cpu.data[0xc0] = 0x15;
+ cpu.data[28] = 0xc0; // Y <- 0xc0
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(1);
+ expect(cpu.cycles).toEqual(1);
+ expect(cpu.data[8]).toEqual(0x15);
+ expect(cpu.data[28]).toEqual(0xc0); // verify that Y was unchanged
+ });
+
+ it('should execute `LD r3, Y+` instruction', () => {
+ loadProgram('3990');
+ cpu.data[0xc0] = 0x15;
+ cpu.data[28] = 0xc0; // Y <- 0xc0
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(1);
+ expect(cpu.cycles).toEqual(2);
+ expect(cpu.data[3]).toEqual(0x15);
+ expect(cpu.data[28]).toEqual(0xc1); // verify that Y was incremented
+ });
+
+ it('should execute `LD r0, -Y` instruction', () => {
+ loadProgram('0a90');
+ cpu.data[0x98] = 0x22;
+ cpu.data[28] = 0x99; // Y <- 0x99
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(1);
+ expect(cpu.cycles).toEqual(3);
+ expect(cpu.data[0]).toEqual(0x22);
+ expect(cpu.data[28]).toEqual(0x98); // verify that Y was decremented
+ });
+
+ it('should execute `LDD r4, Y+2` instruction', () => {
+ loadProgram('4a80');
+ cpu.data[0x82] = 0x33;
+ cpu.data[28] = 0x80; // Y <- 0x80
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(1);
+ expect(cpu.cycles).toEqual(3);
+ expect(cpu.data[4]).toEqual(0x33);
+ expect(cpu.data[28]).toEqual(0x80); // verify that Y was unchanged
+ });
+
+ it('should execute `LD r5, Z` instruction', () => {
+ loadProgram('5080');
+ cpu.data[0xcc] = 0xf5;
+ cpu.data[30] = 0xcc; // Z <- 0xcc
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(1);
+ expect(cpu.cycles).toEqual(1);
+ expect(cpu.data[5]).toEqual(0xf5);
+ expect(cpu.data[30]).toEqual(0xcc); // verify that Z was unchanged
+ });
+
+ it('should execute `LD r7, Z+` instruction', () => {
+ loadProgram('7190');
+ cpu.data[0xc0] = 0x25;
+ cpu.data[30] = 0xc0; // Z <- 0xc0
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(1);
+ expect(cpu.cycles).toEqual(2);
+ expect(cpu.data[7]).toEqual(0x25);
+ expect(cpu.data[30]).toEqual(0xc1); // verify that Y was incremented
+ });
+
+ it('should execute `LD r0, -Z` instruction', () => {
+ loadProgram('0290');
+ cpu.data[0x9e] = 0x66;
+ cpu.data[30] = 0x9f; // Z <- 0x9f
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(1);
+ expect(cpu.cycles).toEqual(3);
+ expect(cpu.data[0]).toEqual(0x66);
+ expect(cpu.data[30]).toEqual(0x9e); // verify that Y was decremented
+ });
+
+ it('should execute `LDD r15, Z+31` instruction', () => {
+ loadProgram('f78c');
+ cpu.data[0x9f] = 0x33;
+ cpu.data[30] = 0x80; // Z <- 0x80
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(1);
+ expect(cpu.cycles).toEqual(3);
+ expect(cpu.data[15]).toEqual(0x33);
+ expect(cpu.data[30]).toEqual(0x80); // verify that Z was unchanged
+ });
+
it('should execute `RJMP 2` instruction', () => {
loadProgram('01c0');
avrInstruction(cpu);
@@ -137,14 +225,14 @@ describe('avrInstruction', () => {
cpu.data[28] = 0x9a; // Y <- 0x9a
avrInstruction(cpu);
expect(cpu.pc).toEqual(1);
- expect(cpu.cycles).toEqual(2);
+ expect(cpu.cycles).toEqual(1);
expect(cpu.data[0x9a]).toEqual(0x5b);
expect(cpu.data[28]).toEqual(0x9a); // verify that Y was unchanged
});
it('should execute `ST Y+, r1` instruction', () => {
loadProgram('1992');
- cpu.data[1] = 0x5a; // r1 <- 5a
+ cpu.data[1] = 0x5a; // r1 <- 0x5a
cpu.data[28] = 0x9a; // Y <- 0x9a
avrInstruction(cpu);
expect(cpu.pc).toEqual(1);
@@ -155,7 +243,7 @@ describe('avrInstruction', () => {
it('should execute `ST -Y, r1` instruction', () => {
loadProgram('1a92');
- cpu.data[1] = 0x5a; // r1 <- 5a
+ cpu.data[1] = 0x5a; // r1 <- 0x5a
cpu.data[28] = 0x9a; // Y <- 0x9a
avrInstruction(cpu);
expect(cpu.pc).toEqual(1);
@@ -166,7 +254,7 @@ describe('avrInstruction', () => {
it('should execute `STD Y+17, r0` instruction', () => {
loadProgram('098a');
- cpu.data[0] = 0xba; // r0 <- ba
+ cpu.data[0] = 0xba; // r0 <- 0xba
cpu.data[28] = 0x9a; // Y <- 0x9a
avrInstruction(cpu);
expect(cpu.pc).toEqual(1);
@@ -181,7 +269,7 @@ describe('avrInstruction', () => {
cpu.data[30] = 0x40; // Z <- 0x40
avrInstruction(cpu);
expect(cpu.pc).toEqual(1);
- expect(cpu.cycles).toEqual(2);
+ expect(cpu.cycles).toEqual(1);
expect(cpu.data[0x40]).toEqual(0xdf);
expect(cpu.data[30]).toEqual(0x40); // verify that Z was unchanged
});
diff --git a/src/instruction.ts b/src/instruction.ts
index 6eafb19..7eaa105 100644
--- a/src/instruction.ts
+++ b/src/instruction.ts
@@ -210,7 +210,7 @@ export function avrInstruction(cpu: ICPU) {
/* LDX, 1001 000d dddd 1101 */
if ((opcode & 0xfe0f) === 0x900d) {
const x = cpu.dataView.getUint16(26, true);
- cpu.data[(opcode & 0x1f0) >> 4] = x;
+ cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(x);
cpu.dataView.setUint16(26, x + 1, true);
cpu.cycles++;
}
@@ -225,42 +225,68 @@ export function avrInstruction(cpu: ICPU) {
/* LDY, 1000 000d dddd 1000 */
if ((opcode & 0xfe0f) === 0x8008) {
- /* not implemented */
+ cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(cpu.dataView.getUint16(28, true));
}
/* LDY, 1001 000d dddd 1001 */
if ((opcode & 0xfe0f) === 0x9009) {
- /* not implemented */
+ const y = cpu.dataView.getUint16(28, true);
+ cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(y);
+ cpu.dataView.setUint16(28, y + 1, true);
+ cpu.cycles++;
}
/* LDY, 1001 000d dddd 1010 */
if ((opcode & 0xfe0f) === 0x900a) {
- /* not implemented */
+ 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;
}
- /* LDY, 10q0 qq0d dddd 1qqq */
- if ((opcode & 0xd208) === 0x8008) {
- /* not implemented */
+ /* LDDY, 10q0 qq0d dddd 1qqq */
+ if (
+ (opcode & 0xd208) === 0x8008 &&
+ (opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8)
+ ) {
+ cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(
+ cpu.dataView.getUint16(28, true) +
+ ((opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8))
+ );
+ cpu.cycles += 2;
}
/* LDZ, 1000 000d dddd 0000 */
if ((opcode & 0xfe0f) === 0x8000) {
- /* not implemented */
+ cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(cpu.dataView.getUint16(30, true));
}
/* LDZ, 1001 000d dddd 0001 */
if ((opcode & 0xfe0f) === 0x9001) {
- /* not implemented */
+ const z = cpu.dataView.getUint16(30, true);
+ cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(z);
+ cpu.dataView.setUint16(30, z + 1, true);
+ cpu.cycles++;
}
/* LDZ, 1001 000d dddd 0010 */
if ((opcode & 0xfe0f) === 0x9002) {
- /* not implemented */
+ 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;
}
- /* LDZ, 10q0 qq0d dddd 0qqq */
- if ((opcode & 0xd208) === 0x8000) {
- /* not implemented */
+ /* LDDZ, 10q0 qq0d dddd 0qqq */
+ if (
+ (opcode & 0xd208) === 0x8000 &&
+ (opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8)
+ ) {
+ cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(
+ cpu.dataView.getUint16(30, true) +
+ ((opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8))
+ );
+ cpu.cycles += 2;
}
/* LPM, 1001 0101 1100 1000 */
@@ -473,7 +499,10 @@ export function avrInstruction(cpu: ICPU) {
}
/* STDY, 10q0 qq1r rrrr 1qqq */
- if ((opcode & 0xd208) === 0x8208) {
+ if (
+ (opcode & 0xd208) === 0x8208 &&
+ (opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8)
+ ) {
cpu.writeData(
cpu.dataView.getUint16(28, true) +
((opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8)),
@@ -504,7 +533,10 @@ export function avrInstruction(cpu: ICPU) {
}
/* STDZ, 10q0 qq1r rrrr 0qqq */
- if ((opcode & 0xd208) === 0x8200) {
+ if (
+ (opcode & 0xd208) === 0x8200 &&
+ (opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8)
+ ) {
cpu.writeData(
cpu.dataView.getUint16(30, true) +
((opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8)),