aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorUri Shaked2019-11-19 22:54:51 +0200
committerUri Shaked2019-11-19 22:54:51 +0200
commit0d2be60ec05fef04cd234d444f72a183baaeb49c (patch)
treeb725a7ae84a45f48ec1921e7fc7ea9c29435c1c8 /src
parentdoc: avr8js → AVR8js (diff)
downloadavr8js-0d2be60ec05fef04cd234d444f72a183baaeb49c.tar.gz
avr8js-0d2be60ec05fef04cd234d444f72a183baaeb49c.tar.bz2
avr8js-0d2be60ec05fef04cd234d444f72a183baaeb49c.zip
feat: CALL, INC, RET, RETI, ROR instructions
Diffstat (limited to '')
-rw-r--r--src/instruction.spec.ts79
-rw-r--r--src/instruction.ts41
2 files changed, 106 insertions, 14 deletions
diff --git a/src/instruction.spec.ts b/src/instruction.spec.ts
index 29c9a49..99c904d 100644
--- a/src/instruction.spec.ts
+++ b/src/instruction.spec.ts
@@ -15,6 +15,16 @@ describe('avrInstruction', () => {
}
}
+ it('should execute `CALL` instruction', () => {
+ loadProgram('0e945c00');
+ cpu.data[93] = 150; // SP <- 50
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(0x5c);
+ expect(cpu.data[150]).toEqual(2); // return addr
+ expect(cpu.data[93]).toEqual(148); // SP should be decremented
+ expect(cpu.cycles).toEqual(5);
+ });
+
it('should execute `CPC r27, r18` instruction', () => {
loadProgram('b207');
cpu.data[18] = 0x1;
@@ -34,20 +44,31 @@ describe('avrInstruction', () => {
expect(cpu.data[95]).toEqual(53); // SREG 00110101 - HSNC
});
- it('should execute `JMP 0xb8` instruction', () => {
- loadProgram('0c945c00');
+ it('should execute `INC r5` instruction', () => {
+ loadProgram('5394');
+ cpu.data[5] = 0x7f;
avrInstruction(cpu);
- expect(cpu.pc).toEqual(0x5c);
- expect(cpu.cycles).toEqual(3);
+ expect(cpu.data[5]).toEqual(0x80);
+ expect(cpu.pc).toEqual(1);
+ expect(cpu.cycles).toEqual(1);
+ expect(cpu.data[95]).toEqual(0x0c); // SREG 00001100 NV
});
- it('should execute `OUT 0x3f, r1` instruction', () => {
- loadProgram('1fbe');
- cpu.data[1] = 0x5a; // r1 <- 0x5a
+ it('should execute `INC r5` instruction when r5 == 0xff', () => {
+ loadProgram('5394');
+ cpu.data[5] = 0xff;
avrInstruction(cpu);
- expect(cpu.pc).toEqual(0x1);
+ expect(cpu.data[5]).toEqual(0);
+ expect(cpu.pc).toEqual(1);
expect(cpu.cycles).toEqual(1);
- expect(cpu.data[0x5f]).toEqual(0x5a);
+ expect(cpu.data[95]).toEqual(2); // SREG 00000010 - Z
+ });
+
+ it('should execute `JMP 0xb8` instruction', () => {
+ loadProgram('0c945c00');
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(0x5c);
+ expect(cpu.cycles).toEqual(3);
});
it('should execute `LDI r28, 0xff` instruction', () => {
@@ -179,6 +200,36 @@ describe('avrInstruction', () => {
expect(cpu.data[30]).toEqual(0x80); // verify that Z was unchanged
});
+ it('should execute `OUT 0x3f, r1` instruction', () => {
+ loadProgram('1fbe');
+ cpu.data[1] = 0x5a; // r1 <- 0x5a
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(0x1);
+ expect(cpu.cycles).toEqual(1);
+ expect(cpu.data[0x5f]).toEqual(0x5a);
+ });
+
+ it('should execute `RET` instruction', () => {
+ loadProgram('0895');
+ cpu.data[93] = 0x90; // SP <- 0x90
+ cpu.data[0x92] = 16;
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(16);
+ expect(cpu.cycles).toEqual(5);
+ expect(cpu.data[93]).toEqual(0x92); // SP should increment
+ });
+
+ it('should execute `RETI` instruction', () => {
+ loadProgram('1895');
+ cpu.data[93] = 0xc0; // SP <- 0xc0
+ cpu.data[0xc2] = 200;
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(200);
+ expect(cpu.cycles).toEqual(5);
+ expect(cpu.data[93]).toEqual(0xc2); // SP should increment
+ expect(cpu.data[95]).toEqual(0x80); // SREG 10000000 I
+ });
+
it('should execute `RJMP 2` instruction', () => {
loadProgram('01c0');
avrInstruction(cpu);
@@ -186,6 +237,16 @@ describe('avrInstruction', () => {
expect(cpu.cycles).toEqual(2);
});
+ it('should execute `ROR r0` instruction', () => {
+ loadProgram('0794');
+ cpu.data[0] = 0x11; // r0 <- 0x11
+ avrInstruction(cpu);
+ expect(cpu.pc).toEqual(1);
+ expect(cpu.cycles).toEqual(1);
+ expect(cpu.data[0]).toEqual(0x08); // r0 should be right-shifted
+ expect(cpu.data[95]).toEqual(0x19); // SREG 00011001 SVI
+ });
+
it('should execute `ST X, r1` instruction', () => {
loadProgram('1c92');
cpu.data[1] = 0x5a; // r1 <- 0x5a
diff --git a/src/instruction.ts b/src/instruction.ts
index a0d7492..f520143 100644
--- a/src/instruction.ts
+++ b/src/instruction.ts
@@ -73,7 +73,14 @@ export function avrInstruction(cpu: ICPU) {
/* CALL, 1001 010k kkkk 111k kkkk kkkk kkkk kkkk */
if ((opcode & 0xfe0e) === 0x940e) {
- /* not implemented */
+ const k = cpu.progMem[cpu.pc + 1] | ((opcode & 1) << 16) | ((opcode & 0x1f0) << 13);
+ const ret = cpu.pc + 2;
+ const sp = cpu.dataView.getUint16(93, true);
+ cpu.data[sp] = 255 & ret;
+ cpu.data[sp - 1] = (ret >> 8) & 255;
+ cpu.dataView.setUint16(93, sp - 2, true);
+ cpu.pc = k - 1;
+ cpu.cycles += 4;
}
/* CBI, 1001 1000 AAAA Abbb */
@@ -168,7 +175,15 @@ export function avrInstruction(cpu: ICPU) {
/* INC, 1001 010d dddd 0011 */
if ((opcode & 0xfe0f) === 0x9403) {
- /* not implemented */
+ const d = cpu.data[(opcode & 0x1f0) >> 4];
+ const r = (d + 1) & 255;
+ cpu.data[(opcode & 0x1f0) >> 4] = r;
+ let sreg = cpu.data[95];
+ sreg = (sreg & 0xfd) | (0 === r ? 2 : 0);
+ sreg = (sreg & 0xfb) | (0 !== (128 & r) ? 4 : 0);
+ sreg = (sreg & 0xf7) | (127 === d ? 8 : 0);
+ sreg = (sreg & 0xef) | (((sreg >> 2) & 1) ^ ((sreg >> 3) & 1) ? 0x10 : 0);
+ cpu.data[95] = sreg;
}
/* JMP, 1001 010k kkkk 110k kkkk kkkk kkkk kkkk */
@@ -376,12 +391,19 @@ export function avrInstruction(cpu: ICPU) {
/* RET, 1001 0101 0000 1000 */
if (opcode === 0x9508) {
- /* not implemented */
+ const i = cpu.dataView.getUint16(93, true) + 2;
+ cpu.dataView.setUint16(93, i, true);
+ cpu.pc = (cpu.data[i - 1] << 8) + cpu.data[i] - 1;
+ cpu.cycles += 4;
}
/* RETI, 1001 0101 0001 1000 */
if (opcode === 0x9518) {
- /* not implemented */
+ const i = cpu.dataView.getUint16(93, true) + 2;
+ cpu.dataView.setUint16(93, i, true);
+ cpu.pc = (cpu.data[i - 1] << 8) + cpu.data[i] - 1;
+ cpu.cycles += 4;
+ cpu.data[95] |= 0x80; // Enable interrupts
}
/* RJMP, 1100 kkkk kkkk kkkk */
@@ -392,7 +414,16 @@ export function avrInstruction(cpu: ICPU) {
/* ROR, 1001 010d dddd 0111 */
if ((opcode & 0xfe0f) === 0x9407) {
- /* not implemented */
+ const d = cpu.data[(opcode & 0x1f0) >> 4];
+ const r = (d >>> 1) | ((cpu.data[95] & 1) << 7);
+ cpu.data[(opcode & 0x1f0) >> 4] = r;
+ let sreg = cpu.data[95];
+ sreg = (sreg & 0xfd) | (0 === r ? 2 : 0);
+ sreg = (sreg & 0xfb) | (0 !== (128 & r) ? 4 : 0);
+ sreg = (sreg & 0xfe) | (1 & d ? 1 : 0);
+ sreg = (sreg & 0xf7) | (((sreg >> 2) & 1) ^ (sreg & 1) ? 8 : 0);
+ sreg = (sreg & 0xef) | (((sreg >> 2) & 1) ^ ((sreg >> 3) & 1) ? 0x10 : 0);
+ cpu.data[95] = sreg;
}
/* SBC, 0000 10rd dddd rrrr */