Commit e80cfcfc authored by bellard's avatar bellard

SPARC merge


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1179 c046a42c-6fe2-441c-8c8c-71466251a162
parent 9772c73b
......@@ -50,7 +50,7 @@ install: all
install -m 644 pc-bios/bios.bin pc-bios/vgabios.bin \
pc-bios/vgabios-cirrus.bin \
pc-bios/ppc_rom.bin \
pc-bios/proll.bin \
pc-bios/proll.elf \
pc-bios/linux_boot.bin "$(datadir)"
mkdir -p "$(docdir)"
install -m 644 qemu-doc.html qemu-tech.html "$(docdir)"
......@@ -107,7 +107,7 @@ tarbin:
$(datadir)/vgabios.bin \
$(datadir)/vgabios-cirrus.bin \
$(datadir)/ppc_rom.bin \
$(datadir)/proll.bin \
$(datadir)/proll.elf \
$(datadir)/linux_boot.bin \
$(docdir)/qemu-doc.html \
$(docdir)/qemu-tech.html \
......
......@@ -175,6 +175,7 @@ endif
ifeq ($(CONFIG_DARWIN),yes)
OP_CFLAGS+= -mdynamic-no-pic
LIBS+=-lmx
endif
#########################################################
......@@ -300,7 +301,7 @@ VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o mixeng.o
endif
ifeq ($(TARGET_ARCH), sparc)
VL_OBJS+= sun4m.o tcx.o lance.o iommu.o sched.o m48t08.o magic-load.o timer.o
VL_OBJS+= sun4m.o tcx.o lance.o iommu.o m48t08.o magic-load.o slavio_intctl.o slavio_timer.o slavio_serial.o fdc.o
endif
ifdef CONFIG_GDBSTUB
VL_OBJS+=gdbstub.o
......
......@@ -261,7 +261,7 @@ int cpu_exec(CPUState *env1)
}
#elif defined(TARGET_SPARC)
if (interrupt_request & CPU_INTERRUPT_HARD) {
do_interrupt(0, 0, 0, 0, 0);
do_interrupt(env->interrupt_index, 0, 0, 0, 0);
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
} else if (interrupt_request & CPU_INTERRUPT_TIMER) {
//do_interrupt(0, 0, 0, 0, 0);
......
......@@ -9,9 +9,7 @@
#include "disas.h"
/* Filled in by elfload.c. Simplistic, but will do for now. */
unsigned int disas_num_syms;
void *disas_symtab;
const char *disas_strtab;
struct syminfo *syminfos = NULL;
/* Get LENGTH bytes from info's buffer, at target address memaddr.
Transfer them to myaddr. */
......@@ -203,19 +201,23 @@ const char *lookup_symbol(void *orig_addr)
{
unsigned int i;
/* Hack, because we know this is x86. */
Elf32_Sym *sym = disas_symtab;
for (i = 0; i < disas_num_syms; i++) {
if (sym[i].st_shndx == SHN_UNDEF
|| sym[i].st_shndx >= SHN_LORESERVE)
continue;
if (ELF_ST_TYPE(sym[i].st_info) != STT_FUNC)
continue;
if ((long)orig_addr >= sym[i].st_value
&& (long)orig_addr < sym[i].st_value + sym[i].st_size)
return disas_strtab + sym[i].st_name;
Elf32_Sym *sym;
struct syminfo *s;
for (s = syminfos; s; s = s->next) {
sym = s->disas_symtab;
for (i = 0; i < s->disas_num_syms; i++) {
if (sym[i].st_shndx == SHN_UNDEF
|| sym[i].st_shndx >= SHN_LORESERVE)
continue;
if (ELF_ST_TYPE(sym[i].st_info) != STT_FUNC)
continue;
if ((long)orig_addr >= sym[i].st_value
&& (long)orig_addr < sym[i].st_value + sym[i].st_size)
return s->disas_strtab + sym[i].st_name;
}
}
return "";
}
......
......@@ -9,7 +9,11 @@ void monitor_disas(target_ulong pc, int nb_insn, int is_physical, int flags);
const char *lookup_symbol(void *orig_addr);
/* Filled in by elfload.c. Simplistic, but will do for now. */
extern unsigned int disas_num_syms;
extern void *disas_symtab; /* FIXME: includes are a mess --RR */
extern const char *disas_strtab;
extern struct syminfo {
unsigned int disas_num_syms;
void *disas_symtab;
const char *disas_strtab;
struct syminfo *next;
} *syminfos;
#endif /* _QEMU_DISAS_H */
......@@ -298,11 +298,7 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
}
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
registers[64] = tswapl(env->y);
tmp = (0<<28) | (4<<24) | env->psr \
| (env->psrs? PSR_S : 0) \
| (env->psrs? PSR_PS : 0) \
| (env->psret? PSR_ET : 0) \
| env->cwp;
tmp = GET_PSR(env);
registers[65] = tswapl(tmp);
registers[66] = tswapl(env->wim);
registers[67] = tswapl(env->tbr);
......@@ -317,7 +313,7 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
{
uint32_t *registers = (uint32_t *)mem_buf, tmp;
uint32_t *registers = (uint32_t *)mem_buf;
int i;
/* fill in g0..g7 */
......@@ -334,12 +330,7 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
}
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
env->y = tswapl(registers[64]);
tmp = tswapl(registers[65]);
env->psr = tmp & ~PSR_ICC;
env->psrs = (tmp & PSR_S)? 1 : 0;
env->psrps = (tmp & PSR_PS)? 1 : 0;
env->psret = (tmp & PSR_ET)? 1 : 0;
env->cwp = (tmp & PSR_CWP);
PUT_PSR(env, tswapl(registers[65]));
env->wim = tswapl(registers[66]);
env->tbr = tswapl(registers[67]);
env->pc = tswapl(registers[68]);
......@@ -495,8 +486,10 @@ static void gdb_vm_stopped(void *opaque, int reason)
/* disable single step if it was enable */
cpu_single_step(cpu_single_env, 0);
if (reason == EXCP_DEBUG)
if (reason == EXCP_DEBUG) {
tb_flush(cpu_single_env);
ret = SIGTRAP;
}
else
ret = 0;
snprintf(buf, sizeof(buf), "S%02x", ret);
......
......@@ -21,6 +21,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* The controller is used in Sun4m systems in a slightly different
* way. There are changes in DOR register and DMA is not available.
*/
#include "vl.h"
/********************************************************/
......@@ -90,6 +94,16 @@ typedef struct fdrive_t {
uint8_t ro; /* Is read-only */
} fdrive_t;
#ifdef TARGET_SPARC
#define DMA_read_memory(a,b,c,d)
#define DMA_write_memory(a,b,c,d)
#define DMA_register_channel(a,b,c)
#define DMA_hold_DREQ(a)
#define DMA_release_DREQ(a)
#define DMA_get_channel_mode(a) (0)
#define DMA_schedule(a)
#endif
static void fd_init (fdrive_t *drv, BlockDriverState *bs)
{
/* Drive */
......@@ -455,6 +469,18 @@ static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
}
}
static CPUReadMemoryFunc *fdctrl_mem_read[3] = {
fdctrl_read,
fdctrl_read,
fdctrl_read,
};
static CPUWriteMemoryFunc *fdctrl_mem_write[3] = {
fdctrl_write,
fdctrl_write,
fdctrl_write,
};
static void fd_change_cb (void *opaque)
{
fdrive_t *drv = opaque;
......@@ -473,7 +499,7 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
BlockDriverState **fds)
{
fdctrl_t *fdctrl;
// int io_mem;
int io_mem;
int i;
FLOPPY_DPRINTF("init controller\n");
......@@ -504,11 +530,8 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
fdctrl_reset(fdctrl, 0);
fdctrl->state = FD_CTRL_ACTIVE;
if (mem_mapped) {
FLOPPY_ERROR("memory mapped floppy not supported by now !\n");
#if 0
io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write);
cpu_register_physical_memory(base, 0x08, io_mem);
#endif
io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write, fdctrl);
cpu_register_physical_memory(io_base, 0x08, io_mem);
} else {
register_ioport_read(io_base + 0x01, 5, 1, &fdctrl_read, fdctrl);
register_ioport_read(io_base + 0x07, 1, 1, &fdctrl_read, fdctrl);
......
......@@ -117,8 +117,6 @@ typedef struct IOMMUState {
uint32_t iostart;
} IOMMUState;
static IOMMUState *ps;
static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr)
{
IOMMUState *s = opaque;
......@@ -187,25 +185,61 @@ static CPUWriteMemoryFunc *iommu_mem_write[3] = {
iommu_mem_writew,
};
uint32_t iommu_translate(uint32_t addr)
uint32_t iommu_translate_local(void *opaque, uint32_t addr)
{
uint32_t *iopte = (void *)(ps->regs[1] << 4), pa;
IOMMUState *s = opaque;
uint32_t *iopte = (void *)(s->regs[1] << 4), pa;
iopte += ((addr - ps->iostart) >> PAGE_SHIFT);
cpu_physical_memory_rw((uint32_t)iopte, (void *) &pa, 4, 0);
iopte += ((addr - s->iostart) >> PAGE_SHIFT);
cpu_physical_memory_read((uint32_t)iopte, (void *) &pa, 4);
bswap32s(&pa);
pa = (pa & IOPTE_PAGE) << 4; /* Loose higher bits of 36 */
return pa + (addr & PAGE_MASK);
}
void iommu_init(uint32_t addr)
static void iommu_save(QEMUFile *f, void *opaque)
{
IOMMUState *s = opaque;
int i;
qemu_put_be32s(f, &s->addr);
for (i = 0; i < sizeof(struct iommu_regs); i += 4)
qemu_put_be32s(f, &s->regs[i]);
qemu_put_be32s(f, &s->iostart);
}
static int iommu_load(QEMUFile *f, void *opaque, int version_id)
{
IOMMUState *s = opaque;
int i;
if (version_id != 1)
return -EINVAL;
qemu_get_be32s(f, &s->addr);
for (i = 0; i < sizeof(struct iommu_regs); i += 4)
qemu_put_be32s(f, &s->regs[i]);
qemu_get_be32s(f, &s->iostart);
return 0;
}
static void iommu_reset(void *opaque)
{
IOMMUState *s = opaque;
memset(s->regs, 0, sizeof(struct iommu_regs));
s->iostart = 0;
}
void *iommu_init(uint32_t addr)
{
IOMMUState *s;
int iommu_io_memory;
s = qemu_mallocz(sizeof(IOMMUState));
if (!s)
return;
return NULL;
s->addr = addr;
......@@ -213,6 +247,8 @@ void iommu_init(uint32_t addr)
cpu_register_physical_memory(addr, sizeof(struct iommu_regs),
iommu_io_memory);
ps = s;
register_savevm("iommu", addr, 1, iommu_save, iommu_load, s);
qemu_register_reset(iommu_reset, s);
return s;
}
......@@ -147,6 +147,7 @@ struct lance_init_block {
};
#define LEDMA_REGS 4
#define LEDMA_MAXADDR (LEDMA_REGS * 4 - 1)
#if 0
/* Structure to describe the current status of DMA registers on the Sparc */
struct sparc_dma_registers {
......@@ -157,32 +158,28 @@ struct sparc_dma_registers {
};
#endif
typedef struct LEDMAState {
uint32_t addr;
uint32_t regs[LEDMA_REGS];
} LEDMAState;
typedef struct LANCEState {
uint32_t paddr;
NetDriverState *nd;
uint32_t leptr;
uint16_t addr;
uint16_t regs[LE_MAXREG];
uint8_t phys[6]; /* mac address */
int irq;
LEDMAState *ledma;
unsigned int rxptr, txptr;
uint32_t ledmaregs[LEDMA_REGS];
} LANCEState;
static unsigned int rxptr, txptr;
static void lance_send(void *opaque);
static void lance_reset(LANCEState *s)
static void lance_reset(void *opaque)
{
LANCEState *s = opaque;
memcpy(s->phys, s->nd->macaddr, 6);
rxptr = 0;
txptr = 0;
s->rxptr = 0;
s->txptr = 0;
memset(s->regs, 0, LE_MAXREG * 2);
s->regs[LE_CSR0] = LE_C0_STOP;
memset(s->ledmaregs, 0, LEDMA_REGS * 4);
}
static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
......@@ -190,7 +187,7 @@ static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
LANCEState *s = opaque;
uint32_t saddr;
saddr = addr - s->paddr;
saddr = addr & LE_MAXREG;
switch (saddr >> 1) {
case LE_RDP:
return s->regs[s->addr];
......@@ -208,7 +205,7 @@ static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val
uint32_t saddr;
uint16_t reg;
saddr = addr - s->paddr;
saddr = addr & LE_MAXREG;
switch (saddr >> 1) {
case LE_RDP:
switch(s->addr) {
......@@ -292,7 +289,7 @@ static CPUWriteMemoryFunc *lance_mem_write[3] = {
static int lance_can_receive(void *opaque)
{
LANCEState *s = opaque;
void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
uint32_t dmaptr = s->leptr + s->ledmaregs[3];
struct lance_init_block *ib;
int i;
uint16_t temp;
......@@ -303,7 +300,7 @@ static int lance_can_receive(void *opaque)
ib = (void *) iommu_translate(dmaptr);
for (i = 0; i < RX_RING_SIZE; i++) {
cpu_physical_memory_read(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
temp &= 0xff;
if (temp == (LE_R1_OWN)) {
#ifdef DEBUG_LANCE
......@@ -323,7 +320,7 @@ static int lance_can_receive(void *opaque)
static void lance_receive(void *opaque, const uint8_t *buf, int size)
{
LANCEState *s = opaque;
void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
uint32_t dmaptr = s->leptr + s->ledmaregs[3];
struct lance_init_block *ib;
unsigned int i, old_rxptr, j;
uint16_t temp;
......@@ -333,23 +330,23 @@ static void lance_receive(void *opaque, const uint8_t *buf, int size)
ib = (void *) iommu_translate(dmaptr);
old_rxptr = rxptr;
for (i = rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) {
cpu_physical_memory_read(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
old_rxptr = s->rxptr;
for (i = s->rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) {
cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
if (temp == (LE_R1_OWN)) {
rxptr = (rxptr + 1) & RX_RING_MOD_MASK;
s->rxptr = (s->rxptr + 1) & RX_RING_MOD_MASK;
temp = size;
bswap16s(&temp);
cpu_physical_memory_write(&ib->brx_ring[i].mblength, (void *) &temp, 2);
cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].mblength, (void *) &temp, 2);
#if 0
cpu_physical_memory_write(&ib->rx_buf[i], buf, size);
cpu_physical_memory_write((uint32_t)&ib->rx_buf[i], buf, size);
#else
for (j = 0; j < size; j++) {
cpu_physical_memory_write(((void *)&ib->rx_buf[i]) + j, &buf[j], 1);
cpu_physical_memory_write(((uint32_t)&ib->rx_buf[i]) + j, &buf[j], 1);
}
#endif
temp = LE_R1_POK;
cpu_physical_memory_write(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR;
if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA))
pic_set_irq(s->irq, 1);
......@@ -364,7 +361,7 @@ static void lance_receive(void *opaque, const uint8_t *buf, int size)
static void lance_send(void *opaque)
{
LANCEState *s = opaque;
void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
uint32_t dmaptr = s->leptr + s->ledmaregs[3];
struct lance_init_block *ib;
unsigned int i, old_txptr, j;
uint16_t temp;
......@@ -375,18 +372,18 @@ static void lance_send(void *opaque)
ib = (void *) iommu_translate(dmaptr);
old_txptr = txptr;
for (i = txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) {
cpu_physical_memory_read(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
old_txptr = s->txptr;
for (i = s->txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) {
cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
if (temp == (LE_T1_POK|LE_T1_OWN)) {
cpu_physical_memory_read(&ib->btx_ring[i].length, (void *) &temp, 2);
cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].length, (void *) &temp, 2);
bswap16s(&temp);
temp = (~temp) + 1;
#if 0
cpu_physical_memory_read(&ib->tx_buf[i], pkt_buf, temp);
cpu_physical_memory_read((uint32_t)&ib->tx_buf[i], pkt_buf, temp);
#else
for (j = 0; j < temp; j++) {
cpu_physical_memory_read(((void *)&ib->tx_buf[i]) + j, &pkt_buf[j], 1);
cpu_physical_memory_read((uint32_t)&ib->tx_buf[i] + j, &pkt_buf[j], 1);
}
#endif
......@@ -395,8 +392,8 @@ static void lance_send(void *opaque)
#endif
qemu_send_packet(s->nd, pkt_buf, temp);
temp = LE_T1_POK;
cpu_physical_memory_write(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
txptr = (txptr + 1) & TX_RING_MOD_MASK;
cpu_physical_memory_write((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
s->txptr = (s->txptr + 1) & TX_RING_MOD_MASK;
s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR;
}
}
......@@ -404,24 +401,20 @@ static void lance_send(void *opaque)
static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr)
{
LEDMAState *s = opaque;
LANCEState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addr) >> 2;
if (saddr < LEDMA_REGS)
return s->regs[saddr];
else
return 0;
saddr = (addr & LEDMA_MAXADDR) >> 2;
return s->ledmaregs[saddr];
}
static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
LEDMAState *s = opaque;
LANCEState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addr) >> 2;
if (saddr < LEDMA_REGS)
s->regs[saddr] = val;
saddr = (addr & LEDMA_MAXADDR) >> 2;
s->ledmaregs[saddr] = val;
}
static CPUReadMemoryFunc *ledma_mem_read[3] = {
......@@ -436,33 +429,61 @@ static CPUWriteMemoryFunc *ledma_mem_write[3] = {
ledma_mem_writel,
};
static void lance_save(QEMUFile *f, void *opaque)
{
LANCEState *s = opaque;
int i;
qemu_put_be32s(f, &s->leptr);
qemu_put_be16s(f, &s->addr);
for (i = 0; i < LE_MAXREG; i ++)
qemu_put_be16s(f, &s->regs[i]);
qemu_put_buffer(f, s->phys, 6);
qemu_put_be32s(f, &s->irq);
for (i = 0; i < LEDMA_REGS; i ++)
qemu_put_be32s(f, &s->ledmaregs[i]);
}
static int lance_load(QEMUFile *f, void *opaque, int version_id)
{
LANCEState *s = opaque;
int i;
if (version_id != 1)
return -EINVAL;
qemu_get_be32s(f, &s->leptr);
qemu_get_be16s(f, &s->addr);
for (i = 0; i < LE_MAXREG; i ++)
qemu_get_be16s(f, &s->regs[i]);
qemu_get_buffer(f, s->phys, 6);
qemu_get_be32s(f, &s->irq);
for (i = 0; i < LEDMA_REGS; i ++)
qemu_get_be32s(f, &s->ledmaregs[i]);
return 0;
}
void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr)
{
LANCEState *s;
LEDMAState *led;
int lance_io_memory, ledma_io_memory;
s = qemu_mallocz(sizeof(LANCEState));
if (!s)
return;
s->paddr = leaddr;
s->nd = nd;
s->irq = irq;
lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s);
cpu_register_physical_memory(leaddr, 8, lance_io_memory);
led = qemu_mallocz(sizeof(LEDMAState));
if (!led)
return;
s->ledma = led;
led->addr = ledaddr;
ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, led);
ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, s);
cpu_register_physical_memory(ledaddr, 16, ledma_io_memory);
lance_reset(s);
qemu_add_read_packet(nd, lance_can_receive, lance_receive, s);
register_savevm("lance", leaddr, 1, lance_save, lance_load, s);
qemu_register_reset(lance_reset, s);
}
......@@ -32,19 +32,14 @@
#define NVRAM_PRINTF(fmt, args...) do { } while (0)
#endif
#define NVRAM_MAX_MEM 0xfff0
#define NVRAM_MAX_MEM 0x1ff0
#define NVRAM_MAXADDR 0x1fff
struct m48t08_t {
/* Hardware parameters */
int mem_index;
uint32_t mem_base;
uint16_t size;
/* RTC management */
time_t time_offset;
time_t stop_time;
/* NVRAM storage */
uint8_t lock;
uint16_t addr;
uint8_t *buffer;
};
......@@ -83,14 +78,13 @@ static void set_time (m48t08_t *NVRAM, struct tm *tm)
}
/* Direct access to NVRAM */
void m48t08_write (m48t08_t *NVRAM, uint32_t val)
void m48t08_write (m48t08_t *NVRAM, uint32_t addr, uint8_t val)
{
struct tm tm;
int tmp;
if (NVRAM->addr > NVRAM_MAX_MEM && NVRAM->addr < 0x2000)
NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, NVRAM->addr, val);
switch (NVRAM->addr) {