From 1cbc06407c5d63714195e3e62a7de66b87e702b5 Mon Sep 17 00:00:00 2001 From: Michel Pollet Date: Sun, 4 Apr 2010 12:20:34 +0100 Subject: [PATCH] core: Add support for RAMPZ and refactor instructions Added RAMPZ as an optional IOREG for the core. Factored the [E]I[JMP/CALL] into one blob. Added the ELMP Instruction with RAMPZ support. Signed-off-by: Michel Pollet --- simavr/sim/sim_avr.h | 1 + simavr/sim/sim_core.c | 43 ++++++++++++++++++++++++++++++++----------- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/simavr/sim/sim_avr.h b/simavr/sim/sim_avr.h index 9c2256d..4af20be 100644 --- a/simavr/sim/sim_avr.h +++ b/simavr/sim/sim_avr.h @@ -78,6 +78,7 @@ typedef struct avr_t { uint8_t vector_size; uint8_t signature[3]; uint8_t fuse[4]; + avr_io_addr_t rampz; // optional, only for ELPM/SPM on >64Kb cores // filled by the ELF data, this allow tracking of invalid jumps uint32_t codeend; diff --git a/simavr/sim/sim_core.c b/simavr/sim/sim_core.c index 31c2ab3..1ccae6b 100644 --- a/simavr/sim/sim_core.c +++ b/simavr/sim/sim_core.c @@ -819,22 +819,26 @@ uint16_t avr_run_one(avr_t * avr) STATE("spm\n"); avr_ioctl(avr, AVR_IOCTL_FLASH_SPM, 0); } break; - case 0x9409: { // IJMP Indirect jump + case 0x9409: // IJMP Indirect jump 1001 0100 0000 1001 + case 0x9419: // EIJMP Indirect jump 1001 0100 0001 1001 bit 4 is "indirect" + case 0x9509: // ICALL Indirect Call to Subroutine 1001 0101 0000 1001 + case 0x9519: { // EICALL Indirect Call to Subroutine 1001 0101 0001 1001 bit 8 is "push pc" + int e = opcode & 0x10; + int p = opcode & 0x100; + if (e && !avr->eind) + _avr_invalid_opcode(avr); uint16_t z = avr->data[R_ZL] | (avr->data[R_ZH] << 8); - STATE("ijmp Z[%04x]\n", z << 1); + if (e) + z |= avr->data[avr->eind] << 16; + STATE("%si%s Z[%04x]\n", e?"e":"", p?"call":"jmp", z << 1); + if (p) { + cycle++; + _avr_push16(avr, new_pc >> 1); + } new_pc = z << 1; cycle++; TRACE_JUMP(); } break; - case 0x9509: { // ICALL Indirect Call to Subroutine - uint16_t z = avr->data[R_ZL] | (avr->data[R_ZH] << 8); - STATE("icall Z[%04x]\n", z << 1); - _avr_push16(avr, new_pc >> 1); - new_pc = z << 1; - cycle += 2; - TRACE_JUMP(); - STACK_FRAME_PUSH(); - } break; case 0x9518: // RETI case 0x9508: { // RET new_pc = _avr_pop16(avr) << 1; @@ -890,6 +894,23 @@ uint16_t avr_run_one(avr_t * avr) } cycle += 2; } break; + case 0x9006: + case 0x9007: { // ELPM Extended Load Program Memory 1001 000d dddd 01oo + if (!avr->rampz) + _avr_invalid_opcode(avr); + uint16_t z = avr->data[R_ZL] | (avr->data[R_ZH] << 8) | (avr->data[avr->rampz] << 16); + uint8_t r = (opcode >> 4) & 0x1f; + int op = opcode & 3; + STATE("elpm %s, (Z[%02x:%04x]%s)\n", avr_regname(r), z >> 16, z&0xffff, opcode?"+":""); + _avr_set_r(avr, r, avr->flash[z]); + if (op == 3) { + z++; + _avr_set_r(avr, avr->rampz, z >> 16); + _avr_set_r(avr, R_ZH, z >> 8); + _avr_set_r(avr, R_ZL, z); + } + cycle += 2; + } break; case 0x900c: case 0x900d: case 0x900e: { // LD Load Indirect from Data using X 1001 000r rrrr 11oo -- 2.39.5