full system SPARC emulation (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1087 c046a42c-6fe2-441c-8c8c-71466251a162
diff --git a/.cvsignore b/.cvsignore
index 9fad653..bca4882 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -12,3 +12,4 @@
qemu.pod
sparc-user
qemu-img
+sparc-softmmu
diff --git a/Changelog b/Changelog
index bf8efc5..8bbe6d9 100644
--- a/Changelog
+++ b/Changelog
@@ -17,6 +17,7 @@
- Fixed Fedora Core 2 problems (now you can run qemu without any
LD_ASSUME_KERNEL tricks on FC2)
- DHCP fix for Windows (accept DHCPREQUEST alone)
+ - SPARC system emulation (Blue Swirl)
version 0.6.0:
diff --git a/Makefile.target b/Makefile.target
index 28585c7..ff07be8 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -63,6 +63,26 @@
endif # ARCH = amd64
endif # TARGET_ARCH = ppc
+
+ifeq ($(TARGET_ARCH), sparc)
+
+ifeq ($(ARCH), ppc)
+PROGS+=$(QEMU_SYSTEM)
+endif
+
+ifeq ($(ARCH), i386)
+ifdef CONFIG_SOFTMMU
+PROGS+=$(QEMU_SYSTEM)
+endif
+endif # ARCH = i386
+
+ifeq ($(ARCH), amd64)
+ifdef CONFIG_SOFTMMU
+PROGS+=$(QEMU_SYSTEM)
+endif
+endif # ARCH = amd64
+
+endif # TARGET_ARCH = sparc
endif # !CONFIG_USER_ONLY
ifdef CONFIG_STATIC
@@ -201,6 +221,10 @@
LIBOBJS+= op_helper.o helper.o
endif
+ifeq ($(TARGET_ARCH), sparc)
+LIBOBJS+= op_helper.o helper.o
+endif
+
# NOTE: the disassembler code is only needed for debugging
LIBOBJS+=disas.o
ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
@@ -254,6 +278,9 @@
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
endif
+ifeq ($(TARGET_ARCH), sparc)
+VL_OBJS+= sun4m.o tcx.o lance.o iommu.o sched.o m48t08.o magic-load.o
+endif
ifdef CONFIG_GDBSTUB
VL_OBJS+=gdbstub.o
endif
@@ -325,7 +352,7 @@
endif
ifeq ($(TARGET_ARCH), sparc)
-op.o: op.c op_template.h
+op.o: op.c op_template.h op_mem.h
endif
ifeq ($(TARGET_ARCH), ppc)
diff --git a/configure b/configure
index 54f1a9f..5d7eed6 100755
--- a/configure
+++ b/configure
@@ -27,7 +27,7 @@
make="make"
strip="strip"
cpu=`uname -m`
-target_list="i386-user i386 i386-softmmu arm-user sparc-user ppc-user ppc-softmmu"
+target_list="i386-user i386 i386-softmmu arm-user sparc-user ppc-user ppc-softmmu sparc-softmmu"
case "$cpu" in
i386|i486|i586|i686|i86pc|BePC)
cpu="i386"
@@ -99,7 +99,7 @@
if [ ! "$darwin" = "yes" ] ; then
make="gmake"
fi
- target_list="i386-softmmu ppc-softmmu"
+ target_list="i386-softmmu ppc-softmmu sparc-softmmu"
fi
# find source path
@@ -160,7 +160,7 @@
strip="${cross_prefix}${strip}"
if test "$mingw32" = "yes" ; then
- target_list="i386-softmmu ppc-softmmu"
+ target_list="i386-softmmu ppc-softmmu sparc-softmmu"
EXESUF=".exe"
gdbstub="no"
fi
diff --git a/cpu-exec.c b/cpu-exec.c
index 053c0cc..930bd7b 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -208,6 +208,11 @@
env->exception_next_eip, 0);
#elif defined(TARGET_PPC)
do_interrupt(env);
+#elif defined(TARGET_SPARC)
+ do_interrupt(env->exception_index,
+ 0,
+ env->error_code,
+ env->exception_next_pc, 0);
#endif
}
env->exception_index = -1;
@@ -261,6 +266,14 @@
env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
}
}
+#elif defined(TARGET_SPARC)
+ if (interrupt_request & CPU_INTERRUPT_HARD) {
+ do_interrupt(0, 0, 0, 0, 0);
+ env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+ } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
+ //do_interrupt(0, 0, 0, 0, 0);
+ env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
+ }
#endif
if (interrupt_request & CPU_INTERRUPT_EXITTB) {
env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
diff --git a/exec-all.h b/exec-all.h
index b6853a1..2e886e0 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -56,6 +56,7 @@
extern uint16_t gen_opc_buf[OPC_BUF_SIZE];
extern uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
extern uint32_t gen_opc_pc[OPC_BUF_SIZE];
+extern uint32_t gen_opc_npc[OPC_BUF_SIZE];
extern uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
@@ -541,8 +542,7 @@
extern int tb_invalidated_flag;
-#if (defined(TARGET_I386) || defined(TARGET_PPC)) && \
- !defined(CONFIG_USER_ONLY)
+#if !defined(CONFIG_USER_ONLY)
void tlb_fill(unsigned long addr, int is_write, int is_user,
void *retaddr);
@@ -585,6 +585,8 @@
is_user = ((env->hflags & HF_CPL_MASK) == 3);
#elif defined (TARGET_PPC)
is_user = msr_pr;
+#elif defined (TARGET_SPARC)
+ is_user = (env->psrs == 0);
#else
#error "Unimplemented !"
#endif
diff --git a/exec.c b/exec.c
index c33661b..f266bb9 100644
--- a/exec.c
+++ b/exec.c
@@ -1077,7 +1077,7 @@
breakpoint is reached */
int cpu_breakpoint_insert(CPUState *env, target_ulong pc)
{
-#if defined(TARGET_I386) || defined(TARGET_PPC)
+#if defined(TARGET_I386) || defined(TARGET_PPC) || defined(TARGET_SPARC)
int i;
for(i = 0; i < env->nb_breakpoints; i++) {
@@ -1099,7 +1099,7 @@
/* remove a breakpoint */
int cpu_breakpoint_remove(CPUState *env, target_ulong pc)
{
-#if defined(TARGET_I386) || defined(TARGET_PPC)
+#if defined(TARGET_I386) || defined(TARGET_PPC) || defined(TARGET_SPARC)
int i;
for(i = 0; i < env->nb_breakpoints; i++) {
if (env->breakpoints[i] == pc)
@@ -1122,7 +1122,7 @@
CPU loop after each instruction */
void cpu_single_step(CPUState *env, int enabled)
{
-#if defined(TARGET_I386) || defined(TARGET_PPC)
+#if defined(TARGET_I386) || defined(TARGET_PPC) || defined(TARGET_SPARC)
if (env->singlestep_enabled != enabled) {
env->singlestep_enabled = enabled;
/* must flush all the translated code to avoid inconsistancies */
diff --git a/gdbstub.c b/gdbstub.c
index 1962310..e15216a 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -157,42 +157,40 @@
#if defined(TARGET_I386)
-static void to_le32(uint8_t *p, int v)
-{
- p[0] = v;
- p[1] = v >> 8;
- p[2] = v >> 16;
- p[3] = v >> 24;
-}
-
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
+ uint32_t *registers = (uint32_t *)mem_buf;
int i, fpus;
for(i = 0; i < 8; i++) {
- to_le32(mem_buf + i * 4, env->regs[i]);
+ registers[i] = env->regs[i];
}
- to_le32(mem_buf + 8 * 4, env->eip);
- to_le32(mem_buf + 9 * 4, env->eflags);
- to_le32(mem_buf + 10 * 4, env->segs[R_CS].selector);
- to_le32(mem_buf + 11 * 4, env->segs[R_SS].selector);
- to_le32(mem_buf + 12 * 4, env->segs[R_DS].selector);
- to_le32(mem_buf + 13 * 4, env->segs[R_ES].selector);
- to_le32(mem_buf + 14 * 4, env->segs[R_FS].selector);
- to_le32(mem_buf + 15 * 4, env->segs[R_GS].selector);
+ registers[8] = env->eip;
+ registers[9] = env->eflags;
+ registers[10] = env->segs[R_CS].selector;
+ registers[11] = env->segs[R_SS].selector;
+ registers[12] = env->segs[R_DS].selector;
+ registers[13] = env->segs[R_ES].selector;
+ registers[14] = env->segs[R_FS].selector;
+ registers[15] = env->segs[R_GS].selector;
/* XXX: convert floats */
for(i = 0; i < 8; i++) {
memcpy(mem_buf + 16 * 4 + i * 10, &env->fpregs[i], 10);
}
- to_le32(mem_buf + 36 * 4, env->fpuc);
+ registers[36] = env->fpuc;
fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
- to_le32(mem_buf + 37 * 4, fpus);
- to_le32(mem_buf + 38 * 4, 0); /* XXX: convert tags */
- to_le32(mem_buf + 39 * 4, 0); /* fiseg */
- to_le32(mem_buf + 40 * 4, 0); /* fioff */
- to_le32(mem_buf + 41 * 4, 0); /* foseg */
- to_le32(mem_buf + 42 * 4, 0); /* fooff */
- to_le32(mem_buf + 43 * 4, 0); /* fop */
+ registers[37] = fpus;
+ registers[38] = 0; /* XXX: convert tags */
+ registers[39] = 0; /* fiseg */
+ registers[40] = 0; /* fioff */
+ registers[41] = 0; /* foseg */
+ registers[42] = 0; /* fooff */
+ registers[43] = 0; /* fop */
+
+ for(i = 0; i < 16; i++)
+ tswapls(®isters[i]);
+ for(i = 36; i < 44; i++)
+ tswapls(®isters[i]);
return 44 * 4;
}
@@ -204,8 +202,8 @@
for(i = 0; i < 8; i++) {
env->regs[i] = tswapl(registers[i]);
}
- env->eip = registers[8];
- env->eflags = registers[9];
+ env->eip = tswapl(registers[8]);
+ env->eflags = tswapl(registers[9]);
#if defined(CONFIG_USER_ONLY)
#define LOAD_SEG(index, sreg)\
if (tswapl(registers[index]) != env->segs[sreg].selector)\
@@ -220,15 +218,6 @@
}
#elif defined (TARGET_PPC)
-static void to_le32(uint32_t *buf, uint32_t v)
-{
- uint8_t *p = (uint8_t *)buf;
- p[3] = v;
- p[2] = v >> 8;
- p[1] = v >> 16;
- p[0] = v >> 24;
-}
-
static uint32_t from_le32 (uint32_t *buf)
{
uint8_t *p = (uint8_t *)buf;
@@ -243,24 +232,24 @@
/* fill in gprs */
for(i = 0; i < 32; i++) {
- to_le32(®isters[i], env->gpr[i]);
+ registers[i] = tswapl(env->gpr[i]);
}
/* fill in fprs */
for (i = 0; i < 32; i++) {
- to_le32(®isters[(i * 2) + 32], *((uint32_t *)&env->fpr[i]));
- to_le32(®isters[(i * 2) + 33], *((uint32_t *)&env->fpr[i] + 1));
+ registers[(i * 2) + 32] = tswapl(*((uint32_t *)&env->fpr[i]));
+ registers[(i * 2) + 33] = tswapl(*((uint32_t *)&env->fpr[i] + 1));
}
/* nip, msr, ccr, lnk, ctr, xer, mq */
- to_le32(®isters[96], (uint32_t)env->nip/* - 4*/);
- to_le32(®isters[97], _load_msr(env));
+ registers[96] = tswapl(env->nip);
+ registers[97] = tswapl(_load_msr(env));
tmp = 0;
for (i = 0; i < 8; i++)
tmp |= env->crf[i] << (32 - ((i + 1) * 4));
- to_le32(®isters[98], tmp);
- to_le32(®isters[99], env->lr);
- to_le32(®isters[100], env->ctr);
- to_le32(®isters[101], _load_xer(env));
- to_le32(®isters[102], 0);
+ registers[98] = tswapl(tmp);
+ registers[99] = tswapl(env->lr);
+ registers[100] = tswapl(env->ctr);
+ registers[101] = tswapl(_load_xer(env));
+ registers[102] = 0;
return 103 * 4;
}
@@ -272,22 +261,90 @@
/* fill in gprs */
for (i = 0; i < 32; i++) {
- env->gpr[i] = from_le32(®isters[i]);
+ env->gpr[i] = tswapl(registers[i]);
}
/* fill in fprs */
for (i = 0; i < 32; i++) {
- *((uint32_t *)&env->fpr[i]) = from_le32(®isters[(i * 2) + 32]);
- *((uint32_t *)&env->fpr[i] + 1) = from_le32(®isters[(i * 2) + 33]);
+ *((uint32_t *)&env->fpr[i]) = tswapl(registers[(i * 2) + 32]);
+ *((uint32_t *)&env->fpr[i] + 1) = tswapl(registers[(i * 2) + 33]);
}
/* nip, msr, ccr, lnk, ctr, xer, mq */
- env->nip = from_le32(®isters[96]);
- _store_msr(env, from_le32(®isters[97]));
- registers[98] = from_le32(®isters[98]);
+ env->nip = tswapl(registers[96]);
+ _store_msr(env, tswapl(registers[97]));
+ registers[98] = tswapl(registers[98]);
for (i = 0; i < 8; i++)
env->crf[i] = (registers[98] >> (32 - ((i + 1) * 4))) & 0xF;
- env->lr = from_le32(®isters[99]);
- env->ctr = from_le32(®isters[100]);
- _store_xer(env, from_le32(®isters[101]));
+ env->lr = tswapl(registers[99]);
+ env->ctr = tswapl(registers[100]);
+ _store_xer(env, tswapl(registers[101]));
+}
+#elif defined (TARGET_SPARC)
+static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
+{
+ uint32_t *registers = (uint32_t *)mem_buf, tmp;
+ int i;
+
+ /* fill in g0..g7 */
+ for(i = 0; i < 7; i++) {
+ registers[i] = tswapl(env->gregs[i]);
+ }
+ /* fill in register window */
+ for(i = 0; i < 24; i++) {
+ registers[i + 8] = tswapl(env->regwptr[i]);
+ }
+ /* fill in fprs */
+ for (i = 0; i < 32; i++) {
+ registers[i + 32] = tswapl(*((uint32_t *)&env->fpr[i]));
+ }
+ /* 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;
+ registers[65] = tswapl(tmp);
+ registers[66] = tswapl(env->wim);
+ registers[67] = tswapl(env->tbr);
+ registers[68] = tswapl(env->pc);
+ registers[69] = tswapl(env->npc);
+ registers[70] = tswapl(env->fsr);
+ registers[71] = 0; /* csr */
+ registers[72] = 0;
+
+ return 73 * 4;
+}
+
+static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
+{
+ uint32_t *registers = (uint32_t *)mem_buf, tmp;
+ int i;
+
+ /* fill in g0..g7 */
+ for(i = 0; i < 7; i++) {
+ env->gregs[i] = tswapl(registers[i]);
+ }
+ /* fill in register window */
+ for(i = 0; i < 24; i++) {
+ env->regwptr[i] = tswapl(registers[i]);
+ }
+ /* fill in fprs */
+ for (i = 0; i < 32; i++) {
+ *((uint32_t *)&env->fpr[i]) = tswapl(registers[i + 32]);
+ }
+ /* 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);
+ env->wim = tswapl(registers[66]);
+ env->tbr = tswapl(registers[67]);
+ env->pc = tswapl(registers[68]);
+ env->npc = tswapl(registers[69]);
+ env->fsr = tswapl(registers[70]);
}
#else
diff --git a/monitor.c b/monitor.c
index ad0f315..15b54d3 100644
--- a/monitor.c
+++ b/monitor.c
@@ -883,18 +883,18 @@
typedef struct MonitorDef {
const char *name;
int offset;
- int (*get_value)(struct MonitorDef *md);
+ int (*get_value)(struct MonitorDef *md, int val);
} MonitorDef;
#if defined(TARGET_I386)
-static int monitor_get_pc (struct MonitorDef *md)
+static int monitor_get_pc (struct MonitorDef *md, int val)
{
return cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base;
}
#endif
#if defined(TARGET_PPC)
-static int monitor_get_ccr (struct MonitorDef *md)
+static int monitor_get_ccr (struct MonitorDef *md, int val)
{
unsigned int u;
int i;
@@ -906,7 +906,7 @@
return u;
}
-static int monitor_get_msr (struct MonitorDef *md)
+static int monitor_get_msr (struct MonitorDef *md, int val)
{
return (cpu_single_env->msr[MSR_POW] << MSR_POW) |
(cpu_single_env->msr[MSR_ILE] << MSR_ILE) |
@@ -925,7 +925,7 @@
(cpu_single_env->msr[MSR_LE] << MSR_LE);
}
-static int monitor_get_xer (struct MonitorDef *md)
+static int monitor_get_xer (struct MonitorDef *md, int val)
{
return (cpu_single_env->xer[XER_SO] << XER_SO) |
(cpu_single_env->xer[XER_OV] << XER_OV) |
@@ -933,25 +933,38 @@
(cpu_single_env->xer[XER_BC] << XER_BC);
}
-uint32_t cpu_ppc_load_decr (CPUState *env);
-static int monitor_get_decr (struct MonitorDef *md)
+static int monitor_get_decr (struct MonitorDef *md, int val)
{
return cpu_ppc_load_decr(cpu_single_env);
}
-uint32_t cpu_ppc_load_tbu (CPUState *env);
-static int monitor_get_tbu (struct MonitorDef *md)
+static int monitor_get_tbu (struct MonitorDef *md, int val)
{
return cpu_ppc_load_tbu(cpu_single_env);
}
-uint32_t cpu_ppc_load_tbl (CPUState *env);
-static int monitor_get_tbl (struct MonitorDef *md)
+static int monitor_get_tbl (struct MonitorDef *md, int val)
{
return cpu_ppc_load_tbl(cpu_single_env);
}
#endif
+#if defined(TARGET_SPARC)
+static int monitor_get_psr (struct MonitorDef *md, int val)
+{
+ return (0<<28) | (4<<24) | cpu_single_env->psr \
+ | (cpu_single_env->psrs? PSR_S : 0) \
+ | (cpu_single_env->psrs? PSR_PS : 0) \
+ | (cpu_single_env->psret? PSR_ET : 0) \
+ | cpu_single_env->cwp;
+}
+
+static int monitor_get_reg(struct MonitorDef *md, int val)
+{
+ return cpu_single_env->regwptr[val];
+}
+#endif
+
static MonitorDef monitor_defs[] = {
#ifdef TARGET_I386
@@ -1037,6 +1050,78 @@
{ "sr14", offsetof(CPUState, sr[14]) },
{ "sr15", offsetof(CPUState, sr[15]) },
/* Too lazy to put BATs and SPRs ... */
+#elif defined(TARGET_SPARC)
+ { "g0", offsetof(CPUState, gregs[0]) },
+ { "g1", offsetof(CPUState, gregs[1]) },
+ { "g2", offsetof(CPUState, gregs[2]) },
+ { "g3", offsetof(CPUState, gregs[3]) },
+ { "g4", offsetof(CPUState, gregs[4]) },
+ { "g5", offsetof(CPUState, gregs[5]) },
+ { "g6", offsetof(CPUState, gregs[6]) },
+ { "g7", offsetof(CPUState, gregs[7]) },
+ { "o0", 0, monitor_get_reg },
+ { "o1", 1, monitor_get_reg },
+ { "o2", 2, monitor_get_reg },
+ { "o3", 3, monitor_get_reg },
+ { "o4", 4, monitor_get_reg },
+ { "o5", 5, monitor_get_reg },
+ { "o6", 6, monitor_get_reg },
+ { "o7", 7, monitor_get_reg },
+ { "l0", 8, monitor_get_reg },
+ { "l1", 9, monitor_get_reg },
+ { "l2", 10, monitor_get_reg },
+ { "l3", 11, monitor_get_reg },
+ { "l4", 12, monitor_get_reg },
+ { "l5", 13, monitor_get_reg },
+ { "l6", 14, monitor_get_reg },
+ { "l7", 15, monitor_get_reg },
+ { "i0", 16, monitor_get_reg },
+ { "i1", 17, monitor_get_reg },
+ { "i2", 18, monitor_get_reg },
+ { "i3", 19, monitor_get_reg },
+ { "i4", 20, monitor_get_reg },
+ { "i5", 21, monitor_get_reg },
+ { "i6", 22, monitor_get_reg },
+ { "i7", 23, monitor_get_reg },
+ { "pc", offsetof(CPUState, pc) },
+ { "npc", offsetof(CPUState, npc) },
+ { "y", offsetof(CPUState, y) },
+ { "psr", 0, &monitor_get_psr, },
+ { "wim", offsetof(CPUState, wim) },
+ { "tbr", offsetof(CPUState, tbr) },
+ { "fsr", offsetof(CPUState, fsr) },
+ { "f0", offsetof(CPUState, fpr[0]) },
+ { "f1", offsetof(CPUState, fpr[1]) },
+ { "f2", offsetof(CPUState, fpr[2]) },
+ { "f3", offsetof(CPUState, fpr[3]) },
+ { "f4", offsetof(CPUState, fpr[4]) },
+ { "f5", offsetof(CPUState, fpr[5]) },
+ { "f6", offsetof(CPUState, fpr[6]) },
+ { "f7", offsetof(CPUState, fpr[7]) },
+ { "f8", offsetof(CPUState, fpr[8]) },
+ { "f9", offsetof(CPUState, fpr[9]) },
+ { "f10", offsetof(CPUState, fpr[10]) },
+ { "f11", offsetof(CPUState, fpr[11]) },
+ { "f12", offsetof(CPUState, fpr[12]) },
+ { "f13", offsetof(CPUState, fpr[13]) },
+ { "f14", offsetof(CPUState, fpr[14]) },
+ { "f15", offsetof(CPUState, fpr[15]) },
+ { "f16", offsetof(CPUState, fpr[16]) },
+ { "f17", offsetof(CPUState, fpr[17]) },
+ { "f18", offsetof(CPUState, fpr[18]) },
+ { "f19", offsetof(CPUState, fpr[19]) },
+ { "f20", offsetof(CPUState, fpr[20]) },
+ { "f21", offsetof(CPUState, fpr[21]) },
+ { "f22", offsetof(CPUState, fpr[22]) },
+ { "f23", offsetof(CPUState, fpr[23]) },
+ { "f24", offsetof(CPUState, fpr[24]) },
+ { "f25", offsetof(CPUState, fpr[25]) },
+ { "f26", offsetof(CPUState, fpr[26]) },
+ { "f27", offsetof(CPUState, fpr[27]) },
+ { "f28", offsetof(CPUState, fpr[28]) },
+ { "f29", offsetof(CPUState, fpr[29]) },
+ { "f30", offsetof(CPUState, fpr[30]) },
+ { "f31", offsetof(CPUState, fpr[31]) },
#endif
{ NULL },
};
@@ -1054,7 +1139,7 @@
for(md = monitor_defs; md->name != NULL; md++) {
if (compare_cmd(name, md->name)) {
if (md->get_value) {
- *pval = md->get_value(md);
+ *pval = md->get_value(md, md->offset);
} else {
*pval = *(uint32_t *)((uint8_t *)cpu_single_env + md->offset);
}
diff --git a/slirp/bootp.c b/slirp/bootp.c
index 8ae68af..3924c10 100644
--- a/slirp/bootp.c
+++ b/slirp/bootp.c
@@ -178,7 +178,8 @@
rbp->bp_hlen = 6;
memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, 6);
- rbp->bp_yiaddr = daddr.sin_addr; /* IP address */
+ rbp->bp_yiaddr = daddr.sin_addr; /* Client IP address */
+ rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */
q = rbp->bp_vend;
memcpy(q, rfc1533_cookie, 4);
diff --git a/softmmu_header.h b/softmmu_header.h
index 0bbc368..074d090 100644
--- a/softmmu_header.h
+++ b/softmmu_header.h
@@ -55,6 +55,8 @@
#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
#elif defined (TARGET_PPC)
#define CPU_MEM_INDEX (msr_pr)
+#elif defined (TARGET_SPARC)
+#define CPU_MEM_INDEX ((env->psrs) == 0)
#endif
#define MMUSUFFIX _mmu
@@ -64,6 +66,8 @@
#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
#elif defined (TARGET_PPC)
#define CPU_MEM_INDEX (msr_pr)
+#elif defined (TARGET_SPARC)
+#define CPU_MEM_INDEX ((env->psrs) == 0)
#endif
#define MMUSUFFIX _cmmu
diff --git a/translate-all.c b/translate-all.c
index be3039c..1fbed41 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -46,6 +46,8 @@
uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
#if defined(TARGET_I386)
uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
+#elif defined(TARGET_SPARC)
+uint32_t gen_opc_npc[OPC_BUF_SIZE];
#endif
int code_copy_enabled = 1;
@@ -208,6 +210,7 @@
#elif defined(TARGET_SPARC)
/* XXX: restore npc too */
env->pc = gen_opc_pc[j];
+ env->npc = gen_opc_npc[j];
#elif defined(TARGET_PPC)
{
int type;
diff --git a/vl.c b/vl.c
index 02edc7d..22b1412 100644
--- a/vl.c
+++ b/vl.c
@@ -710,7 +710,7 @@
for(;;) {
ts = *ptimer_head;
- if (ts->expire_time > current_time)
+ if (!ts || ts->expire_time > current_time)
break;
/* remove timer from the list before calling the callback */
*ptimer_head = ts->next;
@@ -2166,6 +2166,15 @@
{
return 0;
}
+#elif defined(TARGET_SPARC)
+void cpu_save(QEMUFile *f, void *opaque)
+{
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+ return 0;
+}
#else
#warning No CPU save/restore functions
@@ -3336,6 +3345,10 @@
ppc_init(ram_size, vga_ram_size, boot_device,
ds, fd_filename, snapshot,
kernel_filename, kernel_cmdline, initrd_filename);
+#elif defined(TARGET_SPARC)
+ sun4m_init(ram_size, vga_ram_size, boot_device,
+ ds, fd_filename, snapshot,
+ kernel_filename, kernel_cmdline, initrd_filename);
#endif
gui_timer = qemu_new_timer(rt_clock, gui_update, NULL);
diff --git a/vl.h b/vl.h
index 4cfe9c0..8151613 100644
--- a/vl.h
+++ b/vl.h
@@ -664,6 +664,28 @@
extern CPUReadMemoryFunc *PPC_io_read[];
extern int prep_enabled;
+/* sun4m.c */
+void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
+ DisplayState *ds, const char **fd_filename, int snapshot,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename);
+
+/* iommu.c */
+void iommu_init();
+uint32_t iommu_translate(uint32_t addr);
+
+/* lance.c */
+void lance_init(NetDriverState *nd, int irq);
+
+/* tcx.c */
+void tcx_init(DisplayState *ds);
+
+/* sched.c */
+void sched_init();
+
+/* magic-load.c */
+void magic_init(const char *kfn, int kloadaddr);
+
/* NVRAM helpers */
#include "hw/m48t59.h"