From e662916313092382b18676d594bdbb25b5d31682 Mon Sep 17 00:00:00 2001 From: Uri Shaked Date: Thu, 9 Apr 2020 00:21:02 +0300 Subject: feat(instruction): implement EICALL, EIJMP #31 --- src/cpu/instruction.spec.ts | 23 +++++++++++++++++++++++ src/cpu/instruction.ts | 15 +++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/cpu/instruction.spec.ts b/src/cpu/instruction.spec.ts index 0d0d566..4f6e045 100644 --- a/src/cpu/instruction.spec.ts +++ b/src/cpu/instruction.spec.ts @@ -179,6 +179,29 @@ describe('avrInstruction', () => { expect(cpu.cycles).toEqual(3); }); + it('should execute `EICALL` instruction', () => { + cpu = new CPU(new Uint16Array(0x20000)); + loadProgram('EICALL'); + cpu.data[94] = 0; + cpu.data[93] = 0x80; + cpu.data[0x3c] = 1; // EIND <- 1 + cpu.dataView.setUint16(30, 0x1234, true); // Z <- 0x1234 + avrInstruction(cpu); + expect(cpu.pc).toEqual(0x11234); + expect(cpu.cycles).toEqual(4); + expect(cpu.data[0x80]).toEqual(1); // Return address + }); + + it('should execute `EIJMP` instruction', () => { + cpu = new CPU(new Uint16Array(0x20000)); + loadProgram('EIJMP'); + cpu.data[0x3c] = 1; // EIND <- 1 + cpu.dataView.setUint16(30, 0x1040, true); // Z <- 0x1040 + avrInstruction(cpu); + expect(cpu.pc).toEqual(0x11040); + expect(cpu.cycles).toEqual(2); + }); + it('should execute `ELPM` instruction', () => { cpu = new CPU(new Uint16Array(0x20000)); loadProgram('ELPM'); diff --git a/src/cpu/instruction.ts b/src/cpu/instruction.ts index e786bf4..07f1576 100644 --- a/src/cpu/instruction.ts +++ b/src/cpu/instruction.ts @@ -209,6 +209,21 @@ export function avrInstruction(cpu: ICPU) { sreg |= 128 === value ? 8 : 0; sreg |= ((sreg >> 2) & 1) ^ ((sreg >> 3) & 1) ? 0x10 : 0; cpu.data[95] = sreg; + } else if (opcode === 0x9519) { + /* EICALL, 1001 0101 0001 1001 */ + const retAddr = cpu.pc + 1; + const sp = cpu.dataView.getUint16(93, true); + const eind = cpu.data[0x3c]; + cpu.data[sp] = retAddr & 255; + cpu.data[sp - 1] = (retAddr >> 8) & 255; + cpu.dataView.setUint16(93, sp - 2, true); + cpu.pc = ((eind << 16) | cpu.dataView.getUint16(30, true)) - 1; + cpu.cycles += 3; + } else if (opcode === 0x9419) { + /* EIJMP, 1001 0100 0001 1001 */ + const eind = cpu.data[0x3c]; + cpu.pc = ((eind << 16) | cpu.dataView.getUint16(30, true)) - 1; + cpu.cycles++; } else if (opcode === 0x95d8) { /* ELPM, 1001 0101 1101 1000 */ const rampz = cpu.data[0x3b]; -- cgit v1.2.3