aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUri Shaked2019-11-19 22:02:43 +0200
committerUri Shaked2019-11-19 22:02:43 +0200
commit4679710d89098eb3d5cc336ebd2eff8f996b0b94 (patch)
tree08ca36deeb8da526cb7faf8e668892b30b783c1f
parentfeat: implement LDX instructions (diff)
downloadavr8js-4679710d89098eb3d5cc336ebd2eff8f996b0b94.tar.gz
avr8js-4679710d89098eb3d5cc336ebd2eff8f996b0b94.tar.bz2
avr8js-4679710d89098eb3d5cc336ebd2eff8f996b0b94.zip
feat: STY/STZ/STDY/STDZ instructions + tests
-rw-r--r--src/instruction.spec.ts92
-rw-r--r--src/instruction.ts43
2 files changed, 123 insertions, 12 deletions
diff --git a/src/instruction.spec.ts b/src/instruction.spec.ts
index 0cfaf03..f804a85 100644
--- a/src/instruction.spec.ts
+++ b/src/instruction.spec.ts
@@ -43,7 +43,7 @@ describe('avrInstruction', () => {
it('should execute `OUT 0x3f, r1` instruction', () => {
loadProgram('1fbe');
- cpu.data[1] = 0x5a; // put the value 5a in r1
+ cpu.data[1] = 0x5a; // r1 <- 0x5a
avrInstruction(cpu);
expect(cpu.pc).toEqual(0x1);
expect(cpu.cycles).toEqual(1);
@@ -111,7 +111,7 @@ describe('avrInstruction', () => {
it('should execute `ST X+, r1` instruction', () => {
loadProgram('1d92');
- cpu.data[1] = 0x5a; // r1 <- 5a
+ cpu.data[1] = 0x5a; // r1 <- 0x5a
cpu.data[26] = 0x9a; // X <- 0x9a
avrInstruction(cpu);
expect(cpu.pc).toEqual(1);
@@ -130,4 +130,92 @@ describe('avrInstruction', () => {
expect(cpu.data[0x98]).toEqual(0x88);
expect(cpu.data[26]).toEqual(0x98); // verify that X was decremented
});
+
+ it('should execute `ST Y, r2` instruction', () => {
+ loadProgram('2882');
+ cpu.data[2] = 0x5b; // r2 <- 0x5b
+ cpu.data[28] = 0x9a; // Y <- 0x9a
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(1);
+ expect(cpu.cycles).toEqual(2);
+ 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[28] = 0x9a; // Y <- 0x9a
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(1);
+ expect(cpu.cycles).toEqual(1);
+ expect(cpu.data[0x9a]).toEqual(0x5a);
+ expect(cpu.data[28]).toEqual(0x9b); // verify that Y was incremented
+ });
+
+ it('should execute `ST -Y, r1` instruction', () => {
+ loadProgram('1a92');
+ cpu.data[1] = 0x5a; // r1 <- 5a
+ cpu.data[28] = 0x9a; // Y <- 0x9a
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(1);
+ expect(cpu.cycles).toEqual(2);
+ expect(cpu.data[0x99]).toEqual(0x5a);
+ expect(cpu.data[28]).toEqual(0x99); // verify that Y was decremented
+ });
+
+ it('should execute `STD Y+17, r0` instruction', () => {
+ loadProgram('098a');
+ cpu.data[0] = 0xba; // r0 <- ba
+ cpu.data[28] = 0x9a; // Y <- 0x9a
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(1);
+ expect(cpu.cycles).toEqual(2);
+ expect(cpu.data[0x9a + 17]).toEqual(0xba);
+ expect(cpu.data[28]).toEqual(0x9a); // verify that Y was unchanged
+ });
+
+ it('should execute `ST Z, r16` instruction', () => {
+ loadProgram('0083');
+ cpu.data[16] = 0xdf; // r2 <- 0xdf
+ cpu.data[30] = 0x40; // Z <- 0x40
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(1);
+ expect(cpu.cycles).toEqual(2);
+ expect(cpu.data[0x40]).toEqual(0xdf);
+ expect(cpu.data[30]).toEqual(0x40); // verify that Z was unchanged
+ });
+
+ it('should execute `ST Z+, r0` instruction', () => {
+ loadProgram('0192');
+ cpu.data[0] = 0x55; // r0 <- 0x55
+ cpu.dataView.setUint16(30, 0x155, true); // Z <- 0x155
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(1);
+ expect(cpu.cycles).toEqual(1);
+ expect(cpu.data[0x155]).toEqual(0x55);
+ expect(cpu.dataView.getUint16(30, true)).toEqual(0x156); // verify that Z was incremented
+ });
+
+ it('should execute `ST -Z, r16` instruction', () => {
+ loadProgram('0293');
+ cpu.data[16] = 0x5a; // r16 <- 0x5a
+ cpu.data[30] = 0xff; // Z <- 0xff
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(1);
+ expect(cpu.cycles).toEqual(2);
+ expect(cpu.data[0xfe]).toEqual(0x5a);
+ expect(cpu.data[30]).toEqual(0xfe); // verify that Z was decremented
+ });
+
+ it('should execute `STD Z+1, r0` instruction', () => {
+ loadProgram('0182');
+ cpu.data[0] = 0xcc; // r0 <- 0xcc
+ cpu.data[30] = 0x50; // Z <- 0x50
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(1);
+ expect(cpu.cycles).toEqual(2);
+ expect(cpu.data[0x51]).toEqual(0xcc);
+ expect(cpu.data[30]).toEqual(0x50); // verify that Z was unchanged
+ });
});
diff --git a/src/instruction.ts b/src/instruction.ts
index 8e52a80..6eafb19 100644
--- a/src/instruction.ts
+++ b/src/instruction.ts
@@ -452,42 +452,65 @@ export function avrInstruction(cpu: ICPU) {
/* STY, 1000 001r rrrr 1000 */
if ((opcode & 0xfe0f) === 0x8208) {
- /* not implemented */
+ cpu.writeData(cpu.dataView.getUint16(28, true), cpu.data[(opcode & 0x1f0) >> 4]);
}
/* STY, 1001 001r rrrr 1001 */
if ((opcode & 0xfe0f) === 0x9209) {
- /* not implemented */
+ 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);
}
/* STY, 1001 001r rrrr 1010 */
if ((opcode & 0xfe0f) === 0x920a) {
- /* not implemented */
+ const i = cpu.data[(opcode & 0x1f0) >> 4];
+ const y = cpu.dataView.getUint16(28, true) - 1;
+ cpu.dataView.setUint16(28, y, true);
+ cpu.writeData(y, i);
+ cpu.cycles++;
}
- /* STY, 10q0 qq1r rrrr 1qqq */
+ /* STDY, 10q0 qq1r rrrr 1qqq */
if ((opcode & 0xd208) === 0x8208) {
- /* not implemented */
+ cpu.writeData(
+ cpu.dataView.getUint16(28, true) +
+ ((opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8)),
+ cpu.data[(opcode & 0x1f0) >> 4]
+ );
+ cpu.cycles++;
}
/* STZ, 1000 001r rrrr 0000 */
if ((opcode & 0xfe0f) === 0x8200) {
- /* not implemented */
+ cpu.writeData(cpu.dataView.getUint16(30, true), cpu.data[(opcode & 0x1f0) >> 4]);
}
/* STZ, 1001 001r rrrr 0001 */
if ((opcode & 0xfe0f) === 0x9201) {
- /* not implemented */
+ const z = cpu.dataView.getUint16(30, true);
+ cpu.writeData(z, cpu.data[(opcode & 0x1f0) >> 4]);
+ cpu.dataView.setUint16(30, z + 1, true);
}
/* STZ, 1001 001r rrrr 0010 */
if ((opcode & 0xfe0f) === 0x9202) {
- /* not implemented */
+ const i = cpu.data[(opcode & 0x1f0) >> 4];
+ const z = cpu.dataView.getUint16(30, true) - 1;
+ cpu.dataView.setUint16(30, z, true);
+ cpu.writeData(z, i);
+ cpu.cycles++;
}
- /* STZ, 10q0 qq1r rrrr 0qqq */
+ /* STDZ, 10q0 qq1r rrrr 0qqq */
if ((opcode & 0xd208) === 0x8200) {
- /* not implemented */
+ cpu.writeData(
+ cpu.dataView.getUint16(30, true) +
+ ((opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8)),
+ cpu.data[(opcode & 0x1f0) >> 4]
+ );
+ cpu.cycles++;
}
/* SUB, 0001 10rd dddd rrrr */
If you find this content useful please consider a small donation via bitcoin: bitcoin:1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2?amount=0.001&message=Donation Scraping git contents via cgit is very resource intensive. The continued hosting of these git repositories is entirely financed by your bitcoin contributions. For donations of a least 1 mBTC you include your IP address in the message of your bitcoin donation. This will remove this message in the future for requests from your IP, which will significantly reduce token usage. In any case, any contributions to bitcoin address 1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2 are very welcome. Thanks in advance for you contribution to a self-sustaining ecosystem.