forked from sysprog21/semu
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This allows to load and store the emulator state at 0xfff000 in the REU. This way, you can get Linux *running* relatively(!) quickly on a C-64 by avoiding the lengthy boot process.
- Loading branch information
Showing
6 changed files
with
307 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -61,6 +61,7 @@ OBJS := \ | |
plic.o \ | ||
uart.o \ | ||
main.o \ | ||
persistence.o \ | ||
$(OBJS_EXTRA) | ||
|
||
ifeq ($(C64), 1) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
#if !C64 | ||
#include <assert.h> | ||
#endif | ||
#include "device.h" | ||
#include "persistence.h" | ||
|
||
void save_cpu(const vm_t *vm, | ||
uint8_t **obufp) { | ||
for (int i=0; i<32; i++) SER32(vm->x_regs[i]); | ||
SER32(vm->lr_reservation); | ||
SER32(vm->pc); | ||
SER32(vm->current_pc); | ||
SER32(vm->insn_count); | ||
SER32(vm->insn_count_hi); | ||
#if !C64 | ||
assert(vm->error <=255); | ||
#endif | ||
SER8(vm->error); | ||
SER32(vm->exc_cause); | ||
SER32(vm->exc_val); | ||
SER8(vm->s_mode); | ||
SER8(vm->sstatus_spp); | ||
SER8(vm->sstatus_spie); | ||
|
||
SER32(vm->sepc); | ||
SER32(vm->scause); | ||
SER32(vm->stval); | ||
|
||
SER8(vm->sstatus_mxr); | ||
SER8(vm->sstatus_sum); | ||
SER8(vm->sstatus_sie); | ||
|
||
SER32(vm->sie); | ||
SER32(vm->sip); | ||
SER32(vm->stvec_addr); | ||
|
||
SER8(vm->stvec_vectored); | ||
|
||
SER32(vm->sscratch); | ||
SER32(vm->scounteren); | ||
SER32(vm->satp); | ||
SER32(vm->page_table_addr); | ||
} | ||
|
||
static void save_timers(const vm_t *vm, uint8_t **obufp) { | ||
const emu_state_t *data = (const emu_state_t *) vm->priv; | ||
SER32(data->timer_lo); | ||
SER32(data->timer_hi); | ||
} | ||
|
||
void save_all(const vm_t *vm, uint8_t **obufp) { | ||
uint32_t version=1, marker; | ||
SER32(version); | ||
marker='M'; | ||
SER8(marker); // machine | ||
save_cpu(vm, obufp); | ||
|
||
marker='I'; | ||
SER8(marker); // interrupt controller | ||
save_plic(vm, obufp); | ||
marker='U'; | ||
SER8(marker); // UART | ||
save_uart(vm, obufp); | ||
marker='T'; | ||
SER8(marker); | ||
save_timers(vm, obufp); | ||
// FIXME: save network/blockdev devices if they are enabled | ||
} | ||
|
||
void load_cpu(vm_t *vm, | ||
uint8_t **ibufp) { | ||
for (int i=0; i<32; i++) DESER32(vm->x_regs[i]); | ||
DESER32(vm->lr_reservation); | ||
DESER32(vm->pc); | ||
DESER32(vm->current_pc); | ||
DESER32(vm->insn_count); | ||
DESER32(vm->insn_count_hi); | ||
DESER8(vm->error); | ||
DESER32(vm->exc_cause); | ||
DESER32(vm->exc_val); | ||
DESER8(vm->s_mode); | ||
DESER8(vm->sstatus_spp); | ||
DESER8(vm->sstatus_spie); | ||
|
||
DESER32(vm->sepc); | ||
DESER32(vm->scause); | ||
DESER32(vm->stval); | ||
|
||
DESER8(vm->sstatus_mxr); | ||
DESER8(vm->sstatus_sum); | ||
DESER8(vm->sstatus_sie); | ||
|
||
DESER32(vm->sie); | ||
DESER32(vm->sip); | ||
DESER32(vm->stvec_addr); | ||
|
||
DESER8(vm->stvec_vectored); | ||
DESER32(vm->sscratch); | ||
DESER32(vm->scounteren); | ||
DESER32(vm->satp); | ||
DESER32(vm->page_table_addr); | ||
} | ||
|
||
|
||
static void load_timers(vm_t *vm, uint8_t **ibufp) { | ||
emu_state_t *data = (emu_state_t *) vm->priv; | ||
DESER32(data->timer_lo); | ||
DESER32(data->timer_hi); | ||
} | ||
|
||
bool load_all(vm_t *vm, uint8_t **ibufp) { | ||
uint32_t version, marker; | ||
DESER32(version); // version field | ||
if (version != 1) return false; | ||
DESER8(marker); | ||
if (marker != 'M') return false; | ||
load_cpu(vm, ibufp); | ||
DESER8(marker); | ||
if (marker != 'I') return false; | ||
load_plic(vm, ibufp); | ||
DESER8(marker); | ||
if (marker != 'U') return false; | ||
load_uart(vm, ibufp); | ||
DESER8(marker); | ||
if (marker != 'T') return false; | ||
load_timers(vm, ibufp); | ||
// FIXME: load network/blockdev devices if they are enabled | ||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
#pragma once | ||
#include <stdint.h> | ||
#include "riscv.h" | ||
|
||
// set value to 0 in deser first to deal with variable sized fields | ||
|
||
#define SER(value, N) \ | ||
do { \ | ||
uint8_t *obuf = *obufp; \ | ||
uint8_t *v = (uint8_t*)&(value); \ | ||
for (int i=0; i < (N); i++) \ | ||
*obuf++ = v[i]; \ | ||
*obufp+=(N); \ | ||
} while(0); \ | ||
|
||
#define DESER(value, N) \ | ||
do { \ | ||
(value)=0; \ | ||
uint8_t *ibuf = *ibufp; \ | ||
uint8_t *v = (uint8_t*)(&(value)); \ | ||
for (int i=0; i < (N); i++) \ | ||
v[i] = *ibuf++; \ | ||
*ibufp+=(N); \ | ||
} while(0); \ | ||
|
||
#define SER8(value) SER(value, 1) | ||
#define SER32(value) SER(value, 4) | ||
#define DESER8(value) DESER(value, 1) | ||
#define DESER32(value) DESER(value, 4) | ||
|
||
extern void save_cpu(const vm_t *vm, | ||
uint8_t **obufp); | ||
|
||
extern void save_plic(const vm_t *vm, | ||
uint8_t **obufp); | ||
|
||
extern void save_uart(const vm_t *vm, | ||
uint8_t **obufp); | ||
|
||
extern void save_all(const vm_t *vm, uint8_t **obufp); | ||
|
||
extern void load_cpu(vm_t *vm, | ||
uint8_t **ibufp); | ||
|
||
extern void load_plic(vm_t *vm, | ||
uint8_t **ibufp); | ||
|
||
extern void load_uart(vm_t *vm, | ||
uint8_t **ibufp); | ||
|
||
extern bool load_all(vm_t *vm, uint8_t **ibufp); | ||
|
||
#define PERSISTENCE_BASEADR 0xfff000 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters